排序算法4之归并排序
2015-12-21 19:45
489 查看
归并排序
归并排序是建立在归并操作上的一种排序算法,该算法采用分治的思想(divide and conquer)。就是先将序列进行分裂成一个个子序列,使得每个子序列都是有序的,然后再将所有的子序列整合成一个完整的序列。所以整个算法分为两部分,分裂和合并。分裂比较简单,最容易想到的就是折半分解,直至每个子序列是一个单独的数为止。合并就可能麻烦一点。合并
假设存在两个已经排列好的子序列{a1,a2,a3……an}\{a_1,a_2,a_3……a_n\}和{b1,b2,b3……bm}\{b_1,b_2,b_3……b_m\}。我们逐个比较两个子序列中项目的大小,将关键字较小的项目放入一个临时数组中,然后从对应的子序列删除放入的项目,当某个子序列为空时,就可以将另外一个子序列的全部项目依次放入临时数组中。然后利用临时数组给{c1,c2,c3……cn+m}\{c_1,c_2,c_3……c_{n+m}\}赋值。
void MemeryArray(int* p,int first,int middle,int end,int* tmp) { int i=first;//第一个子序列的起始位置 int m=middle;//第一个子序列的终止位置 int j=middle+1;//第二个子序列的起始位置 int n=end;//第二个子序列的终止位置 int k=0; while(i<=m&&j<=n) { if(p[i]<p[j]) tmp[k++]=p[i++]; else tmp[k++]=p[j++]; }//将较小的项目放入临时数组tmp while(i<=m) tmp[k++]=p[i++]; while(j<=n) tmp[k++]=p[j++];//将剩余的某一子序列全部放入临时数组 for(int i=0;i<k;i++)//利用临时数组对原本的序列进行赋值 p[first+i]=tmp[i]; }
上图可以很直接的说明归并排序的思想,下面是完整的归并排序的code
#include<iostream> using namespace std; void MemeryArray(int* p,int first,int middle,int end,int* tmp) { int i=first; int m=middle; int j=middle+1; int n=end; int k=0; while(i<=m&&j<=n) { if(p[i]<p[j]) tmp[k++]=p[i++]; else tmp[k++]=p[j++]; } while(i<=m) tmp[k++]=p[i++]; while(j<=n) tmp[k++]=p[j++]; for(int i=0;i<k;i++) p[first+i]=tmp[i]; }//合并操作 void mergeSort(int* p,int first,int end,int* tmp) { if(first<end)//递归操作的终止条件就是first>=end { int middle=(first+end)/2; mergeSort(p,first,middle,tmp);//分解 mergeSort(p,middle+1,end,tmp);//分解 MemeryArray(p,first,middle,end,tmp);//合并 } } bool MergeSort(int* p,int length) { int* q=new int[length];//由于每次调用归并排序都需要一个临时数组,为了避免麻烦,我们直接创建一个较大的临时数组,供所有的归并排序使用。 if(q==NULL) return false; mergeSort(p,0,length-1,q); delete[] q; return true; } int main() { int data[5]={5,4,3,2,1}; MergeSort(data,sizeof(data)/sizeof(data[0])); for(int i=0;i<sizeof(data)/sizeof(data[0]);i++) cout<<data[i]<<endl; return 0; }
从上面可以分析出来,归并排序的总共会递归调用log2(length)log_2(length)次,而每次调用的主要时间代价就是合并,从合并函数我们知道,每次的需要赋值2∗length2*length次,所以时间复杂度Ω(nlog(n))\Omega(nlog(n));空间复杂度,由于需要额外开辟一个临时数组,所以空间复杂度仍然是Ω(n)\Omega(n);同时归并排序是一种稳定排序。
相关文章推荐
- 非java web 工程脚本案例
- 递归
- 使用装饰器模式动态设置Drawable的ColorFilter
- 生成窗口最大值数组 + 双端队列
- 代码常用工具
- cloudstack F5 管理
- openStreetMap学习网站
- cocoapods的安装和使用
- QT如何在点关闭按钮时执行一些操作
- 关于网站因为翻页而产生标题及描述标签重复的问题
- UNIX学习笔记一
- android读取系统相册返回为空的解决办法
- HTML第一课总结
- String,StringBuffer与StringBuilder的区别
- verilog综合编译后出现占用逻辑资源为0的情况
- 机器学习技术在达观数据的实践
- 初级数据持久化
- 【杭电】[1236]排名
- Android 各种调试方法
- 泛型(集合泛型)