归并排序实现思想及代码实现
归并排序思想
归并排序采用分治的思想,每次都把当前数组分了两半,直到分成一个数据为单位,这里利用递归实现,然后治的过程就是合并的过程。合并的时候顺便排好的序。新建一个临时数组,存放还没排好序的两部分。为排序两部分分别从L 和mid + 1出开始比较。小的数就存放在数组中。
归并排序代码实现
代码实现:
private void MergeSort(int[] array , int n) {
mergeRecursive(array , 0 , n - 1);
}
//归并排序的递归分解函数
//对[ L , R ]区间内数据分解,再合并
private void mergeRecursive(int[] array , int L , int R) {
//if (L >= R)
// return;
if (R - L <= 100) {
insertSortPart(array , L , R);
return;
}
int mid = (L + R)/2;
mergeRecursive(array , L , mid);
mergeRecursive(array , mid + 1 , R);
if (array[mid] > array[mid + 1])
merge(array , L , mid , R);
}
//两个排序后的子数组合并为一个排序好的数组
private void merge(int[] array , int L , int mid , int R) {
int[] temp = new int[R - L + 1];
int tempR = R - L + 1;
for (int i = 0 ; i < tempR ; i ++)
temp[i] = array[i + L];
int indexL = L , indexR = mid + 1;
for (int index = L ; index <= R ; index ++) {
if (indexL > mid) {
array[index] = temp[indexR - L];
indexR ++;
} else if (indexR > R) {
array[index] = temp[indexL - L];
indexL ++;
} else if (temp[indexL - L] <= temp[indexR - L]) {
array[index] = temp[indexL - L];
indexL ++;
} else {
array[index] = temp[indexR - L];
indexR++;
}
}
}
时间复杂度:因为每次分为一半,分了log(n)次,每次都要计算n次,时间复杂度是O(nlongn),,排序也是稳定的。
当数组本来接近有序的,归并也不能退化成O(n),因为还是要递归,分层,但是这个过程中可以避免合并,当 array[mid] < array[mid + 1]时,就不用归并了。
进一步优化是递归终止的条件,当递归到后面时,每个分块的数组长度就很小了,可以使用插入排序,效率更高,因为这时候数据少,数组接近有序,使用插入排序来终止递归效率更高。
优化:
private void mergeRecursive(int[] array , int L , int R) {
//if (L >= R)
// return;
if (R - L <= 15) {
insertSortPart(array , L , R);
return;
}
int mid = (L + R)/2;
mergeRecursive(array , L , mid);
mergeRecursive(array , mid + 1 , R);
if (array[mid] > array[mid + 1])
merge(array , L , mid , R);
}
不使用递归的归并排序
private void mergeSortFromButtonToUp(int[] array , int n) {
for (int len = 1 ; len < n ; len += len)
//两个len进行归并,还要进行越界判断
for (int i = 0 ; i + len < n ; i += (2*len))
merge(array , i , i + len - 1 , Math.min(i + 2*len - 1 , n - 1));
}