实现原理(转自:
递归算法学习系列二(归并排序)
http://www.cnblogs.com/jillzhang/archive/2007/09/16/894936.html)归并排序是利用递归和分而治之的技术将数据序列划分成为越来越小的半子表,再对半子表排序,最后再用递归步骤将排好序的半子表合并成为越来越大的有序序列,归并排序包括两个步骤,分别为:
1)划分子表
2)合并半子表
首先我们来讨论归并算法,归并算法将一系列数据放到一个向量中,索引范围为[first,last],这个序列由两个排好序的子表构成,以索引终点(mid)为分界线,以下面一个序列为例
7,10,19,25,12,17,21,30,48
这样的一个序列中,分为两个子序列 7,10,19,25 和 12,17,21,30,48,如下图所示:
再使用归并算法的时候的步骤如下:
第一步:比较v[indexA]=7和v[indexB]=12,将较小的v[indexA]取出来放到临时向量tempArray中,然后indexA加1
第二步:比较v[indexA]=10和v[indexB]=12,将较小的10放到临时变量tempArray中,然后indexA++;
第三步:比较v[indexA]=19与v[indexB]=12,将较小的12存放到临时变量tempArray中,然后indexB++;
第四步到第七步:按照以上规则,进行比对和存储,得到如下结果:
最后一步:将子表b中剩余项添加到临时向量tempArray中
然后将临时变量中的值按照索引位置,拷贝回向量v中,就完成了对向量v的归并排序
Java实现代码:
package com.sort.merge;
public class Merge {
/**
* 分治法,自顶向下,递归分割数组,最终归并
*/
public static void merge(int[] arr,int start,int end){
if(start<end){
int mid = (start+end)/2;
merge(arr,start,mid);//递归地对arr[start...mid]排序
merge(arr,mid+1,end);//递归地对arr[mid+1...end]排序
doMerge(arr,start,mid,end);//组合,将两个有序区合并为一个有序区
}
}
//组合,归并
public static void doMerge(int[] arr,int start,int mid,int end){
int tempIndex = start;
int Index = start;
int right = mid + 1;
int temp[] = new int[arr.length];
//两个子序列比较,小的放入临时数组
while(start <= mid && right <= end){
if(arr[start] <= arr[right]){
temp[tempIndex++] = arr[start++];
}else{
temp[tempIndex++] = arr[right++];
}
}
//剩下的右边的元素加入临时数组
while(start <= mid){
temp[tempIndex++] = arr[start++];
}
//剩下的右边的元素加入临时数组
while(right <= end){
temp[tempIndex++] = arr[right++];
}
//复制临时数据temp[]中的数据到arr[]数组
while(Index < end){
arr[Index] = temp[Index++];
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[] = {2,4,6,8,1,3,5,9};
merge(arr,0,arr.length-1);
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
}
}
转自:
http://zmling1985.blog.163.com/blog/static/43053310200932841613567/
采用分治法进行自顶向下的算法设计,形式更为简洁。
(1)分治法的三个步骤
设归并排序的当前区间是R[low..high],分治法的三个步骤是:
①分解:将当前区间一分为二,即求分裂点
②求解:递归地对两个子区间R[low..mid]和R[mid+1..high]进行归并排序;
③组合:将已排序的两个子区间R[low..mid]和R[mid+1..high]归并为一个有序的区间R[low..high]。
递归的终结条件:子区间长度为1(一个记录自然有序)。
(2)具体算法
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