归并排序:
该算法符合五大经典算法之中的分治法
分治法每层递归都有三步操作:
1:分解:原问题分解为小问题。
2:解决:把小问题解决。
3:合并:把分解的小问题合并成原问题。
将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并,得到n/2个长度为2的有序表;将这些有序序列再次归并,得到n/4个长度为4的有序序列;如此反复进行下去,最后得到一个长度为n的有序序列。
把问题分成两块来说,
先来看看合并问题。
public void heBing(int a[], int first, int mid, int last){
int i = first; //第一个序列角标
int j = mid + 1; //第二个序列角标
int k = 0; //临时数组角标
int temp[] = new int[last - first + 1]; //临时存放数组
while(i <= mid && j <= last){ //开始比较两个序列的大小,合并为一个有序序列
if(a[i] < a[j]){
temp[k] = a[i];
i ++;
k ++;
}
else{
temp[k] = a[j];
j ++;
k ++;
}
}
if(i <= mid){ //如第一个序列剩余数字直接放到后面
for(; i <= mid; i++){
temp[k] = a[i];
k ++;
}
}
if(j <= last){ //如第二个序列剩余数字直接放到后面
for(; j <= last; j++){
temp[k] = a[j];
j ++;
}
}
for(int f = first, f1 = 0; f <= last; f++ , f1 ++){ //把排好序的数组存入
a[f] = temp[f1];
}
}
之后再做分解:
int[] sort(int list[]){ //进行分解
int length = list.length;
for(int jump = 1; jump < length; jump = jump *2){ //jump设定几个数字一分解
int i = 0;
for(; i + jump * 2 - 1 <length; i = i + jump * 2) //以当前的jump的值进行分解,知道不够再分两组为止
heBing(list, i, i + jump - 1, i + 2 * jump - 1);
if(i + jump - 1 < length){ //检查是否还有剩余数字,有的话拿去继续排序
heBing(list, i, i + jump - 1, length - 1);
}
}
return list;
}
归并算法的时间复杂度为O(nlgn);
其稳定度很高,最好喝最坏情况下都是O(nlgn)