我的Github地址
小码哥《恋上数据结构与算法》笔记
极客时间《iOS开发高手课》笔记
iOS大厂面试高频算法题总结
iOS面试资料汇总
归并排序(Merge Sort)
一、概念
- 不断地将当前序列平均分割成
2
个子序列,直到不能再分割。(序列中只剩1
个元素)
- 不断地将
2
个子序列合并成一个有序序列,直到最终只剩下1
个有序序列。

二、divide(划分)
public class MergeSort<T extends Comparable<T>> extends Sort<T> {
private T[] leftArray;
private void sort(int begin, int end) {
if (end - begin < 2) return;
int mid = (begin + end) >> 1;
sort(begin, mid);
sort(mid, end);
merge(begin, mid, end);
}
}
三、merge(合并)
1、概念
- 两个数组都有一个指向
头节点
的指针。
- 比较两个指针对应值的大小,将小的值取出,并将其指针向后移动一位。
黑色
代表已填入的数据,黄色
代表这一轮比较较小的值。

2、细节
- 需要merge的2组序列存在于同一个数组中,并且是挨在一起的。

- 如果我们将
3
和8
比较的结果放入数组左侧,那么8
的值就会被覆盖。
- 为了更好的完成merge操作,最好将其中一组序列备份出来,比如
[begin, mid)
- 我们将左侧数组复制一份出来,然后进行
merge
操作。

3、实例
黑色
代表已填入的数据,黄色
代表这一轮比较较小的值。

- 左边先结束,右边剩下的无需再排序,可结束排序。

- 右边先结束,左边剩下的可直接搬到右边,结束排序。

4、代码实现
public class MergeSort<T extends Comparable<T>> extends Sort<T> {
private T[] leftArray;
@Override
protected void sort() {
leftArray = (T[]) new Comparable[array.length >> 1];
sort(0, array.length);
}
private void merge(int begin, int mid, int end) {
int li = 0, le = mid - begin;
int ri = mid, re = end;
int ai = begin;
for (int i = li; i < le; i++) {
leftArray[i] = array[begin + i];
}
while (li < le) {
if (ri < re && cmp(array[ri], leftArray[li]) < 0) {
array[ai++] = array[ri++];
} else {
array[ai++] = leftArray[li++];
}
}
}
}
- 由于归并排序总是平均分割子序列,所以最好,最坏,平均时间复杂度都是
O(nlogn)
,属于稳定排序。
- 归并排序的空间复杂度是
O(n)
。
四、算法题
合并两个有序数组
合并两个有序链表
合并k个有序链表