我们在这里主要探讨二路归并排序:
归并的意思是将两个及两个以上的有序表组合成一个新的有序表。
实现的方法是:对两个有序的序列进行遍历并一一比较两个序列当前元素的大小值,假定这两个序列都是升序的,我们要将这两个序列合并成一个升序的,只需要依次去两个序列中的较小值存入新的序列表中,直到两个序列都为空后,我们就得到了合并后的新的有序序列。
归并排序:
- 空间复杂度:需要辅助空间存储合并后的序列,大小为n,所以空间复杂度为O(n)
- 时间复杂度:每趟归并复杂度为O(n),共归并O(logN)趟,故为O(N*logN)
- 稳定性:merge()操作不会改变相同关键字的相对次序,所以二路归并是稳定的排序
代码如下:
//总共需要执行的归并
public static void sort(int a[], int first, int end) {
if(first < end) {
int mid = (first + end) /2;
sort(a, first, mid);
sort(a, mid + 1, end);
merge(a, first, mid, end);
}
}
//一趟归并
public static void merge(int a[], int first, int mid, int last) {
int[] temp = new int[last - first + 1];
int i=first, j=mid+1;
int k=0;
//向辅助数组中添加数据
while(i <= mid && j <= last) {
if(a[i] < a[j]) {
temp[k++] = a[i++];
} else {
temp[k++] = a[j++];
}
}
while(i <= mid) {
temp[k++] = a[i++];
}
while(j <= last) {
temp[k++] = a[j++];
}
//将辅助数组的数据覆盖原数组的数据
for(int l=0; l<k; l++) {
a[first + l] = temp[l];
}
}
测试代码:
public static void main(String[] args) {
int[] a = new int[]{2,1,5,4,7,4,8,3};
sort(a, 0, a.length - 1);
System.out.println(Arrays.toString(a));
}
测试结果:
[1, 2, 3, 4, 4, 5, 7, 8]