归并排序是分治思想体现得最充分的一种排序算法,所谓分治就是把多个问题拆分成若干个更容易解决的小问题
那分治是怎么应用到排序中的呢?
我们以归并排序为例把
如果我们要对它排序,那是不是可以吧它分成两个序列,分别对这两个序列进行排序之后,再将两个有序的序列按找大小合并起来呢?答案是肯定的
归并排序的最基本的思想实际上就是不停地划分序列,直至得到的子序列只有1个,然后将这些子序列按照顺序合并起来,最后得到的新的序列就是有序的,如果你没有看懂,那么下面这张流程图应该会给你一些启发
假设给定乱序的序列:10 3 5 7 100 1 2 9 6 14 12 17 21 25 27
我们首先要做的就是划分序列,一般取中间下标的元素为划分点,当我们划分得到的子序列只有1个元素时,实际上它就是有序的了,这个时候就很容易跟它的相邻子序列进行有序合并,直到将所有序列都合并成功,这样得到的新序列就是有序的了
实际上归并排序的主要流程就是2个:1.划分原序列 2.合并有序序列
假设给定的序列规模为N,那么划分流程的时间复杂度就是O(logN),合并过程的时间复杂度为O(N),所以,整个归并排序的时间复杂度就为O(N*logN),这个复杂度已经是比较排序算法中的下界了,就意味着归并排序是比较排序算法中平均性能最优的算法之一,另外,归并排序是一种稳定的排序算法,因为 大小相同的两个元素在排序前和排序后,他的相对位置是不会改变的
下面贴一下归并排序的C++代码
#include<iostream>
using namespace std;
int data[15] = {10, 3, 5, 7, 100, 1, 2, 9, 6, 14, 12, 17, 21, 25, 27};
void print(int *data, int length){
for(int i = 0; i < length; i++){
if(i == length - 1)
cout << data[i] << endl;
else
cout << data[i] << " ";
}
}
void merge(int *data, int begin, int pos, int end){
int length = end - begin + 1;
int *temp = new int[length];
int k = 0, i = begin, j = pos + 1;
for(; i <= pos && j <= end;){
if(data[i] <= data[j])
temp[k++] = data[i++];
else
temp[k++] = data[j++];
}
while(i <= pos){
temp[k++] = data[i++];
}
while(j <= end){
temp[k++] = data[j++];
}
//更新data
for(int i = begin, kk = 0; i <= end && kk < k; i++, kk++){
data[i] = temp[kk];
}
//回收内存
delete temp;
}
void MergeSort(int *data, int begin, int end){
if(begin < end){
int pos = (begin + end) / 2;
MergeSort(data, begin, pos);
MergeSort(data, pos + 1, end);
merge(data, begin, pos, end);
print(data, 15);
}
}
int main(){
MergeSort(data, 0, 14);
return 0;
}结果:

3万+

被折叠的 条评论
为什么被折叠?



