归并排序
和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间,O(n)的额外空间。该算法是采用分治法 。
归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;
算法思路
- 将长度为n的序列一分为二,分成子序列。
- 子序列继续分,直到子序列只有一个数值,看做有序
- 将有序的俩子序列归并成一个有序序列
递归程序
public int[] mergeSort (int array[]) {
if(array.length < 2)
return array;
int mid = array.length/2;
int[] left = Arrays.copyOfRange(array, 0, mid);
//copy的方法是复制数组的0到mid部分,包括0不包括mid
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(mergeSort(left), mergeSort(right));//递归
}
public int[] merge(int a[], int b[] ) {
//将俩有序子序归并成一个有序序列
int [] c = new int[a.length + b.length ];
//定义C数组时,可不可以放到外面传入参数中直接传入一个临时数组
//这样可不用每次都要创建一个数组c,而是在外面一个数组中进行反复操作
//这样的话,不好用返回值的函数
int i = 0,j = 0,value = 0;
while (i < a.length && j < b.length ) {
if(a[i] <= b[j])
c[value++] = a[i++];
else
c[value++] = b[j++];
}
while(i < a.length )
c[value++] = a[i++];
while(j < b.length )
c[value++] = b[j++];
return c;
}
上面程序中,递归之后,方法返回的是排序好的序列,但是原来序列array没有改变。需要注意。因为是在方法中返回了的merge函数,对形参进行了赋值,方法里面的形参指向了新的地址,而外面的实际参数还是原来的地址。
非递归
非递归的话,首先将序列都分为只有一个数值的子序列,看做有序
之后,有序的子序从1,2,4,8翻倍,一直归并,直到子序的长度大于等于数组大小
public void mergepass(int[] a, int[] tmpa, int s){
// s为 当前有序子列的长度
int i = 0;
while(i+2*s <= a.length ) {
//i+2*s小于等于数组大小,相当于i之后未合并的的元素要大于2*s
merge1(a, tmpa, i, i+s, i+2*s-1);
i=i+2*s;
}
if(i+s < a.length )
// 未合并的元素大于s个,说明可以有俩个子列,一个长度s,一个不足s,归并
merge1(a, tmpa, i, i+s,a.length-1);
else
// 未合并的元素小于等于s个,只有一个子列,直接放在临时数组后面
for(int j = i; j<a.length ; j++)
tmpa[j] = a[j];
}
public void merge1(int[] a, int[] b, int left, int right, int rightend) {
//合并有序子列成一个有序的列,假设俩有序的子列在一个数组里紧挨着
int leftend = right-1;
int tmp = left;
while(left <= leftend && right <= rightend) {
if(a[left] <= a[right])
b[tmp++] = a[left++];
else
b[tmp++] = a[right++];
}
while(left <= leftend)
b[tmp++] = a[left++];
while(right <= rightend)
b[tmp++] = a[right++];
}
public void MergeSORT(int[] a) {
int[] tmpa = new int[a.length ];
int s = 1;
while(s < a.length ) {
mergepass(a, tmpa, s);
s=s*2;//有序的子列长度每次翻倍
mergepass(tmpa, a, s);
//俩次的mergepass目的是最终让排列好的数值在a数组中
s=s*2;
}
}