分治算法-归并排序、快速排序

分治算法:把一个任务,分成形式和原任务相同,但规模更小的几个部分任务(通常是两个部分),分别完成,或只需要选一部完成。然后再处理完成后的这一个或几个部分的结果,实现整个任务的完成。

分治的典型应用:归并排序、快速排序


归并排序动态图:

 1 package com.inbreak.cnblogs.sort;
 2
 3 import com.inbreak.cnblogs.Helper;
 4
 5 /**
 6  * 归并排序:
 7  * 分别前一半、后一半排序
 8  * 将前半部分、后半部分归并到一个有序数组,再拷贝到原数组中。
 9  *
10  * @author inbreak
11  * @create 2018-07-19
12  */
13 public class MergeSort {
14
15     public static void main(int[] a, int size) {
16         Helper.printArray(a);
17         int[] tmp = new int[size];
18         mergeSort(a, 0, size - 1, tmp);
19         Helper.printArray(a);
20     }
21
22     public static void mergeSort(int[] a, int s, int e, int[] tmp) {
23         if (s < e) {
24             int m = (s + e) / 2;
25             mergeSort(a, s, m, tmp);
26             mergeSort(a, m + 1, e, tmp);
27             merge(a, s, m, e, tmp);
28         }
29     }
30
31     public static void merge(int[] a, int s, int m, int e, int[] tmp) {
32         //将s~m和m+1~e合并到tmp数组
33         int pt = 0;
34         int pi = s;
35         int pj = m + 1;
36         //先把左半边或者右半边的拷贝完
37         while (pi <= m && pj <= e) {
38             if (a[pi] < a[pj]) {
39                 tmp[pt++] = a[pi++];
40             } else {
41                 tmp[pt++] = a[pj++];
42             }
43         }
44         //上面的while循环结束,其中的一半全部复制完成,下面的2个while循环只有一个会走
45         //这趟归并的左半部分
46         while (pi <= m) {
47             tmp[pt++] = a[pi++];
48         }
49         //这趟归并的右半部分
50         while (pj <= e) {
51             tmp[pt++] = a[pj++];
52         }
53         //将tmp复制到原数组
54         for (int i = 0; i < e - s + 1; i++) {
55             a[s + i] = tmp[i];
56         }
57     }
58
59 }

快速排序:

 1 package com.inbreak.cnblogs.sort;
 2
 3 import com.inbreak.cnblogs.Helper;
 4
 5 /**
 6  * 快速排序:
 7  * 1)设k=a[0], 将k挪到适当位置,使得比k小的元素都在k左边,比k大的元素都在k右边,和k相等的,不关心在k左右出现均可 (O(n)时间完成)
 8  * 2) 把k左边的部分快速排序
 9  * 3) 把k右边的部分快速排序
10  *
11  * @author inbreak
12  * @create 2018-07-19
13  */
14 public class QuickSort {
15
16     public static void main(int[] a, int size) {
17         Helper.printArray(a);
18         quickSort(a, 0, size - 1);
19         Helper.printArray(a);
20     }
21
22     public static void quickSort(int[] a, int s, int e) {
23         if (s >= e) {
24             return;
25         }
26         int k = a[s];
27         int pi = s;
28         int pj = e;
29         //while循环结束 pi == pj 后的这个就是a[pi] == k,确定这个左边数都比k小,右边都比k大
30         while (pi != pj) {
31             //先从右指针pj往左遍历
32             while (pj > pi && a[pj] >= k) {
33                 pj--;
34             }
35             //pj循环结束后 pj中的值a[pj] < k,此时交换内容,因为默认第一个就是k也就是a[pi]
36             Helper.swap(a, pi, pj);
37             //从左指针pi往右遍历
38             while (pj > pi && a[pi] <= k) {
39                 pi++;
40             }
41             //交换
42             Helper.swap(a, pi, pj);
43         }
44         //针对左、右半部分的递归
45         quickSort(a, s, pi - 1);
46         quickSort(a, pi + 1, e);
47
48     }
49 }

原文地址:https://www.cnblogs.com/peiwei/p/9292078.html

时间: 2024-10-05 23:35:29

分治算法-归并排序、快速排序的相关文章

分治算法——归并排序与快速排序

1.归并排序 分治思想:每次从中间分开为两个子问题,对每个子问题排序完成之后,将两个已排序的部分进行归并操作即得到最终排序的结果. (1)如果数组S中元素个数为0或者1返回 (2)选取中间位置的元素下标,对左半部分SL递归排序,对右半部分SR递归排序 (3)将排好序的SL.SR进行归并后返回最终结果 平均时间复杂度O(NlogN),最坏情况也为O(NlogN),最好情况为O(N). C++模版实现: template <typename T> void TMergeSort(vector<

【从零学习经典算法系列】分治策略实例——快速排序(QuickSort)

在前面的博文(http://blog.csdn.net/jasonding1354/article/details/37736555)中介绍了作为分治策略的经典实例,即归并排序,并给出了递归形式和循环形式的c代码实例.但是归并排序有两个特点,一是在归并(即分治策略中的合并步骤)上花费的功夫较多,二是排序过程中需要使用额外的存储空间(异地排序算法<out of place sort>). 为了节省存储空间,出现了快速排序算法(原地排序in-place sort).快速排序是由东尼·霍尔所发展的一

算法浅谈——分治算法与归并、快速排序(附代码和动图演示)

在之前的文章当中,我们通过海盗分金币问题详细讲解了递归方法. 我们可以认为在递归的过程当中,我们通过函数自己调用自己,将大问题转化成了小问题,因此简化了编码以及建模.今天这篇文章呢,就正式和大家聊一聊将大问题简化成小问题的分治算法的经典使用场景--排序. 排序算法 排序算法有很多,很多博文都有总结,号称有十大经典的排序算法.我们信手拈来就可以说上来很多,比如插入排序.选择排序.桶排序.希尔排序.快速排序.归并排序等等.老实讲这么多排序算法,但我们实际工作中并不会用到那么多,凡是高级语言都有自带的

递归分治算法(一)-归并排序算法

前言: 分治法是一种算法设计思想,所谓分治,意为分而治之,是指将一个难以直接解决的大问题,递归的分割成一些规模的较小的问题,以便逐个解决.采用分治法设计的算法通常用到递归算法来实现,故标题为递归分治. 归并排序算法 归并就是将两个或两个以上的有序表合并成一个新的有序表.归并排序就是将无序的待排序的序列分解成若干个有序的子序列,并把有序子序列合并为整体有序序列的过程.一般分为2-路归并排序和多路归并排序. 他的大概流程如下图: 我们来看看java代码怎么写的: package guibing; /

基于分治算法的归并排序

#include <stdio.h> #include <math.h> void main() { int array[] = {1,212,35,1,456,12376,167,12,7523,71,634}; mergeSort(array, 0, 10); for(int i = 0; i < 11; i++ ) { printf("%d\n", array[i]); } } void mergeSort(int* array, int start

分治算法(二)

大家都知道选择排序和冒泡排序,这两个排序都是双重for循环,时间复杂度为O(n^2),显然效率都是比较低的,而运用分治思想的归并排序和快速排序会更高效一些. 1.归并排序 1)原理:假设初始序列含有n个记录,则可以看成是n个有序子序列,每个子序列的长度为1,然后两两归并,得到[n/2]([x]表示不小于x的最小整数)个长度为2或1的有序子序列:再两两归并,--,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法成为2路归并排序.(摘自<大话数据结构>) 可见其运用了典型的分治思想,①分

五大算法之分治算法

一.基本思想 当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出.对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法.如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止.这就是分治策略的基本思想. 二.二分法 利用分治策略求解时,所需时间取决于分解后子问题的个数.子问题的规模大小等因素,而二分法,由于其划

算法学习——分治算法

这是从网上查到的概念资料,先收来~ 一.基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并.这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)…… 任何一个可以用计算机求解的问题所需的计算时间都与其规模有关.问题的规模越小,越容易直接求解,解题所需的计算时间也越少.例如,对于n个

算法系列之常用算法之一----分治算法

一.基本概念 在计算机科学中,分治法是一种很重要的算法.分治算法,字面上的解释是"分而治之",分治算法主要是三点: 1.将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题----"分" 2.将最后子问题可以简单的直接求解----"治" 3.将所有子问题的解合并起来就是原问题打得解----"合" 这三点是分治算法的主要特点,只要是符合这三个特点的问题都可以使用分治算法进行解决(注意用词,是"