赞
踩
网上很多归并排序文章都是主讲归并排序原理,但对于代码实现部分的见解没有很侧重,所以本章让我们一起来看一下归并算法的代码实现部分。
学习一个算法,首先当然得学习它的原理啦~
归并排序,利用分治法的思想,先将数组折半分组,直至每组只剩一个元素,然后排序合并数组,最终使其变为完全有序数组。
上动画演示,这里引用 “五分钟学算法” up主的动图,觉得不错
动画演示虽是同时分组,但当你调试代码时,你会发现它是先分完一边,再分另一边
还有一张图片我觉得也蛮不错的,很好的体现出分治法的思想。
先看一下合并(merge)部分的实现
void merge(int low,int mid,int high) { int left = low; //左边部分数组指针 int right = mid + 1; //右边部分指针 int k = low; //对temp数组进行操作的指针 while (left < mid + 1 && right < high + 1) { /*这个while是用来将两个数组合并成一个新的 数组的,该数组暂时存放在temp[]里面*/ if (nums[left] > nums[right]) { temp[k++] = nums[right++]; //这里的k++和right++意思是先赋值后加1 } //相当于下面else的写法啦 else { temp[k] = nums[left]; k++; left++; } } //查看左边序列是否为空 while (left < mid + 1) { /*这两个while是当一个数组的值存放完毕时,将另一个数组剩余 的元素依次存入*/ temp[k++] = nums[left++]; } //查看右边序列是否为空 while (right < high + 1) { temp[k++] = nums[right++]; } //移动回原数组,num[i]是定义在全局区待排序的数组 for (int i = low; i <= high; i++) { //这里要i=low阿,不可以等于0 nums[i] = temp[i]; } }
分组(mergeSort)部分的代码实现
void mergeSort(int low,int high) //运用递归啦
{
if(low >= high) { //相当于是单个元素一组了,直接返回就行
return;
}
int mid = low + ((high - low) >> 1);/*防止low和high太大导致越界,>>1和除以2一样,不过
比/2效率快*/
//分
mergeSort(low, mid); //先分左边
mergeSort(mid + 1, high); //分完左边分右边
//治
merge(low, mid, high); //一层一层合并,小数组逐渐合并成大数组
}
最后看一下完整的具体代码
#include <iostream> using namespace std; int nums[7] = { 7,3,5,2,9,8 };//待排序数组 int temp[7];//临时存储数组 void merge(int low,int mid,int high) { int left = low; //左边部分数组指针 int right = mid + 1; //右边部分指针 int k = low; //对temp数组进行操作的指针 while (left < mid + 1 && right < high + 1) { if (nums[left] > nums[right]) { temp[k++] = nums[right++]; } else { temp[k] = nums[left]; k++; left++; } } //查看左边序列是否为空 while (left < mid + 1) { temp[k++] = nums[left++]; } //查看右边序列是否为空 while (right < high + 1) { temp[k++] = nums[right++]; } //移动回原数组 for (int i = low; i <= high; i++) { //这里要i=low阿,不可以等于0 nums[i] = temp[i]; } } void mergeSort(int low,int high) { if(low >= high) { return; } int mid = low + ((high - low) >> 1);//防止low和high太大导致越界,>>1和除以2一样,不过比/2效率快 //分 mergeSort(low, mid); mergeSort(mid + 1, high); //治 merge(low, mid, high); } int main() { mergeSort(0, 5); for (int i = 0; i <=5; i++) { cout << nums[i] << " "; } cout << endl; return 0; }
最好是可以自己调试一下代码,看一下变量值的变化,会对归并算法的实现更加清晰明了。
时间复杂度:
从这个递归树可以看出,第一层时间代价为cn,第二层时间代价为cn/2+cn/2=cn……每一层代价都是cn,总共有logn+1层,所以总的时间代价为cn*(logn+1).时间复杂度是O(nlogn).
空间复杂度: 归并排序算法排序过程中需要额外的一个序列temp[] 去存储排序后的结果,所占空间是n,因此空间复杂度为O(n)
稳定性: 在最坏、最佳、平均情况下归并排序时间复杂度均为O(nlogn).从合并过程中可以看出合并排序稳定。
归并排序算法的效率高,因为它的时间复杂度只有O(nlogn),所以当处理的数据量多的时候,用归并排序是一个不错的选择。对于该算法中的分治思想不太了解的C友可以先查一下概念,而后借助调试帮助理解代码实现。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。