1. 归并排序
“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表。
归并排序的基本思路:
(1)假设初始序列有n个记录,则可以看成n个有序的子序列,每个子序列的长度为1。
(2)然后两两归并,得到[n/2]个长度为2或1(n为奇数的情况)的有序子序列;
(3)两个有序子序列不断归并,重复上一步...
(4)最终得到一个长度为n的子序列。
举一个归并的例子,相同颜色的值为一个子序列:
初始序列 | 49 38 65 97 76 13 27 |
第一次归并之后 | 38 49 65 97 13 76 27 |
第二次归并之后 | 38 49 65 97 13 27 76 |
第三次归并之后 | 13 27 38 49 65 76 97 |
归并排序平均时间复杂度:O(nlogn),最坏时间复杂度:O(nlogn),辅助存储O(n)。
2. Java代码实现
归并排序代码实现 MyMergingSort.java 如下所示。
第二步和第三步((2)然后两两归并,得到[n/2]个长度为2或1(n为奇数的情况)的有序子序列;(3)两个有序子序列不断归并,重复上一步...)是递推进行的,在MyMergingSort.java中我们用递归实现,即和上述的思路正好相反。
package mergingSort;
import java.lang.reflect.Array;
public class MyMergingSort {
private int values[];
public MyMergingSort(int[] values) {
this.values = values;
}
/**
* 两两归并,将两个有序子序列[l, mid] , [mid. r]归并
* mid = (l+r)/2
* @param l 起始坐标
* @param r 终止坐标
*/
public void Merge(int l, int r) {
int[] temp = new int[r-l+1];
int mid=(l+r)/2, i = l, j = mid + 1, index = 0;
while (i <= mid && j <= r) {
if (values[i] < values[j])
temp[index++] = values[i++];
else
temp[index++] = values[j++];
}
if (i <= mid) {
for (int k=i; k<=mid; k++) {
temp[index++] = values[k];
}
}
if (j <= r) {
for (int k=i; k<=r; k++) {
temp[index++] = values[k];
}
}
index = 0;
for (int k=l; k<=r; k++) {
values[k] = temp[index++];
}
}
/**
* 对序列进行归并排序
* @param l 序列起始坐标
* @param r 序列终止坐标
*/
public void MergeSort(int l, int r) {
if (l == r) {
return;
} else {
int mid = (l+r)/2;
MergeSort(l, mid);
MergeSort(mid+1, r);
Merge(l, r);
}
}
}
测试代码,Test.java :
package mergingSort;
public class Test {
public static void main(String args[]) {
int[] arr = new int[]{49, 38, 65, 97, 76, 13, 27};
MyMergingSort myMergingSort = new MyMergingSort(arr);
int length = arr.length;
myMergingSort.MergeSort(0, length-1);
for (int i=0; i<length; i++) {
System.out.print(arr[i]+" ");
}
}
}
运行截图,如下所示:
参考文献
- 数据结构 - 严蔚敏、吴伟民 - 清华大学出版社