归并排序的基本思想是:首先,将 R[0..n-1] 看成是 n 个长度为1的有序表,将相邻的有序表成对归并,得到n/2个长度为2的有序表;然后,再将这些有序表成对归并,得到n/4个长度为4的有序表,如此反复进行下去,最后得到一个长度为n的有序表。
这里引用另一位博主的归并排序原理解析图:
C++代码示例:
void Merge(vector<int> R, int low, int mid, int high) {
int i = low,j = mid + 1; // k是R1的下标,i、j分别为第1、2段的下标
vector<int> R1; // 辅助数组
while (i <= mid && j <= high) { // 在第一段和第二段均未扫描完时循环
if (R[i] <= R[j]) { // 将第一段中的元素放入R1中
R1.push_back(R[i]);
i ++;
}
else { // 将第二段中的元素放入R1中
R1.push_back(R[j]);
j ++;
}
}
while (i <= mid) { // 将第一段余下部分复制到R1
R1.push_back(R[i]);
i ++;
}
while (j <= high) { // 将第二段余下部分复制到R1
R1.push_back(R[j]);
j ++;
}
for (int k = 0,i = low; i <= high; k++,i++) { // 将R1复制回R中
R[i] = R1[k];
}
}
void MergePass(vector<int> R, int length, int n) {
int i;
for (i = 0; i+2*length-1 < n; i = i+2*length) { // 归并length长的相邻两子表
Merge(R, i, i+length-1, i+2*length-1);
}
if (i+length-1 < n) { // 余下两个子表,后者长度小于length
Merge(R, i, i+length-1, n-1); // 归并这两个子表
}
}
void MergeSort(vector<int> R, int n) { // 二路归并算法
int length;
for (length=1; length<n; length=2*length) {
MergePass(R, length, n);
}
}
归并排序算法的性能如下表所示:
时间复杂度 | 空间复杂度 | 稳定性 | 复杂性 |
---|---|---|---|
平均情况: O(nlog2n) | O(n) | 稳定 | 较复杂 |
最坏情况: O(nlog2n) | \ | \ | \ |
最好情况: O(nlog2n) | \ | \ | \ |
从上表可以看出归并排序的时间效率与排序数据序列的顺序无关。
归并排序算法中所产生的有序区不一定是全局有序的,也就是说,有序区中的所有元素的关键字不一定大于或小于无序区中所有元素的关键字。