归并排序:直接上图:
即,它把一个数组不断地划分,直到数组长度为1,然后将相邻
两个有序子数组段合并为一个有序数组段。
一般有两种方式:
(1)采用递归分解
(2)采用非递归方式分解
//递归划分
public class MergeSort {
static int a[]={0,10,20,5,9,35,58,78,54,32,15,28,79,30,50};//数组下标为了从一开始,用0来进行占位
static int b[]=new int[15];
public static void main(String[] args) {
mergeSort(1,14);
for(int i=1;i<b.length;i++)
System.out.print(a[i]+" ");
}
public static void mergeSort(int left,int right) {
// 这里和二分搜索有点像,就是每次将数组划分成两段
if(left<right){
int mid=(left+right)/2;
mergeSort(left, mid);
mergeSort(mid+1, right);
merge(left,mid,right);
copy(a,b,left,right);/*每经历一次一次归并后,记得将数组写会到a数组中,
如果没写回去,之前已经比较好的数组元素都是存在b中的,这样经历
下一次比较后,已经比较好的 元素就会被打乱,大家可以自己试试,感
觉我也描述的不够清楚 */
private static void copy(int[] a2, int[] b2, int left, int right) {
for(int i=left;i<=right;i++)
a[i]=b[i];
}
public static void merge(int left, int mid, int right) {
// TODO Auto-generated method stub
int start=left;
int temp=mid+1;
int index=left;
while((start<=mid)&&(temp<=right)){//两段数组,一个从left到mid,一个从mid+1到right,每次把小的赋值给数组b
if(a[start]<=a[temp]){
b[index++]=a[start++];
}
else{
b[index++]=a[temp++];
}
}
if(start>mid){
for(int i=temp;i<=right;i++)
b[index++]=a[i];
}else{
for(int i=start;i<=mid;i++)
b[index++]=a[i];
}
}
}
//结果
//非递归c++
void mergeSort(Type a[], int n) {
Type *b = new Type[n];
int s = 1;
while(s < n) {
mergePass(a, b, s, n);
s += s;
mergePass(b, a, s, n);
s += s;
}
}
void mergePass(Type a[], Type b[], int s, int n) {
// 功能:合并大小为s的相邻子数组
int i = 0;
while(i < n – 2 * s) {
// 合并大小为s的相邻2段子数组
Merge(a, b, i, i + s - 1, i + 2*s - 1);
i = i + 2 * s;
}
// 剩下的元素个数少于(2*s)个
if(i + s < n) Merge(a, b, i, i + s - 1, n - 1);
else
for(int j = i; j <= n - 1; j++) {b[j] = a[j]; }
}
void Merge(Type a[], Type b[], int l, int m, int r) {
// 功能:合并a[l:m]和a[m+1:r]到b[l:r]
int i = l, j = m + 1, k = l;
while((i <= m) && (j <= r)) {
if(a[i] <= a[j]) b[k++] = a[i++];
else b[k++] = a[j++];
}
if(i > m) for(int q = j; q <= r; q++) b[k++] = a[q];
else for(int q = i; q <= m; q++) b[k++] = a[q];
}