常用算法(4)-归并算法
来源:互联网 发布:淘宝店子账号怎么认证 编辑:程序博客网 时间:2024/06/01 09:50
形象视频:http://v.youku.com/v_show/id_XMzMyODk5Njg4.html
将两个有序的子序列[low,m]和[m,high]归并成一个有序的序列。合并过程中,设置i,j和p三个指针,其初值分别指向这三个记录区的起始位置。合并时以此比较arr[i]和arr[i],取较小的记录复制到arr1[p],然后将i或j,以及p均+1。
void MergeSort(int *arr,int low,int m,int high){ int i,j,p; int *arr1;//缓存向量 i=low; j=m+1; p=0; while(i<=m&&j<=high)//两序列非空时,将较小的输出到向量arr1中 { if(arr[i]<arr[j]) { arr1[p]=arr[i]; p++; i++ } else { arr1[p]=arr[j]; p++; j++; } } while(i<=m)//若该子序列非空,则将剩余的记录记录到arr1中 { arr[p]=arr1[i]; p++; i++ } while(j<=high)//若该子序列非空,则将剩余的记录记录到arr1中 { arr[p]=arr1[j]; p++; j++; } for(i=low,p=0;i<=high;i++,p++) arr[i]=arr1[p];}
1 自底向上的方法
基本思路:第一趟归并排序时,将待排序的arr[0...n]看作是 n个长度为1的有序子文件,将这些子序列两两归并,若n为偶数则得到n/2个长度为2的有序序列;若n为奇数,则最后一个子序列轮空(不参与归并),因此本次归并后得到钱lgn个有序子序列长度为2,但最后一个子序列长度仍为1。第二趟归并则将第一趟归并所得到lgn个有序子序列两两归并,如此反复,直到得到一个长度为n的有序序列为止。上述每次归并,均是将两个有序的子序列合并成一个有序子序列,故称其为“二路归并排序”
代码分析:在某趟归并中,设各子序列长度为length,则归并序列arr[0..n]中有序子序列:[1..length],[length+1....2length],.....,[n/length-1]*length+1.....n]。
在调用归并操作将相邻的一对子序列进行归并时,必须考虑两个问题:1子序列个数是奇数,2最后一各子序列长度小于length,对应的作如下处理,
1.若子序列个数为奇数,则最后一个子序列无须和其他子序列归并,即本趟轮空;
2.若子序列个数为偶数,要注意最后一对子序列中后一个序列的区间上界应该是n;
void MergePass(int *arr,int length){ int i; //归并长度为length的两个相邻子序列 for(i=1;i+2*length-1<=n;i=i+2*length) MergeSort(arr,i,i+length-1,i+2*length-1); //上述循环执行完后,arr数组中保存的是n/length个长度为length的有序子序列 //如果还剩下两个子序列,后者的长度小于length,则设置后者的区间上限为n if(i+length-1<n) MergeSort(arr,i,i+length-1,n) //如果i<=n&&i+length-1>=n,也即n为奇数时,默认剩余的一个那个元素无须归并}//采用自底向上的方法,对arr[1....n]进行2路归并void Merge(int *arr){ int length; for(length=1;length<n;length*=2)//作lgn趟归并 MergePass(arr,lenth); }
2 自顶向下的方法【待研究】
采用分治法进行自顶向下的算法设计,形式更为简洁。 设归并排序的当前区间是R[low..high],分治法的三个步骤是:①分解:将当前区间一分为二,即求分裂点 ②求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序;③组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。 递归的终结条件:子区间长度为1(一个记录自然有序)。 void MergeSortDC(SeqList R,int low,int high) {//用分治法对R[low..high]进行二路归并排序 int mid; if(low<high){//区间长度大于1 mid=(low+high)/2; //分解 MergeSortDC(R,low,mid); //递归地对R[low..mid]排序 MergeSortDC(R,mid+1,high); //递归地对R[mid+1..high]排序 Merge(R,low,mid,high); //组合,将两个有序区归并为一个有序区 } }//MergeSortDC
时间复杂度:对长度为n的序列,需要进行lgn趟二路归并,每趟归并时间复杂度为O(n),所以好或坏的情况下时间复杂度均为O(nlgn)
空间复杂度:需要额外的向量保存结果,空间复杂度为O(n)
属于不稳定排序
参考:http://hi.baidu.com/sleet1986/blog/item/82f0ae8b6b4e38609f2fb4cd.html
- 常用算法(4)-归并算法
- 常用排序算法--归并排序
- 常用排序算法-归并排序
- 归并(合并)算法
- 常用排序算法总结4一一归并排序
- 常用排序算法总结(一)----冒泡排序,归并排序
- 常用排序算法(冒泡、选择、归并、快排、插入)
- 【常用排序算法】归并排序(Java实现)
- 内部排序算法4(归并排序)
- 常用排序算法之归并排序
- 常用算法——归并排序
- 常用内部排序算法之一:归并排序
- 常用排序算法之归并排序
- 常用排序算法——归并排序
- 常用排序算法之归并排序
- 常用排序算法之归并排序
- Java常用算法之归并排序
- 归并算法
- Android中为你的应用程序添加桌面快捷方式
- win7环境下VM+Ubuntu系统设置NAT方式连接网络
- ScrollView中嵌套ListView的问题
- Ext Button的onClick和handler
- Java 中的访问权限总结
- 常用算法(4)-归并算法
- android设置主题和自定义主题的方法
- 第三次作业过晓炜感想
- 类 操作符 重载
- Camel、Pastal、匈牙利标记法
- VC++6.0代码字体修改
- 桌面程序带背景蓝色解决方法
- android如何设置控件的样式
- JDK1.5新特征