归并排序
其基本思想是:对于两个有序序列(集合),将其融合在一起得到一个新的有序序列,又被称为二路归并。
因此,归并排序的过程就是:首先将一个待排序列不断划分,划分为原来的一半,直至子序列只有一个元素为止,此时,每一个子序列只有一个元素,也就是每个子序列都是有序的。这个过程被称为分。再将子序列对应融合,按照一定的大小顺序合并在一起,最终得到有序序列,这个过程被称为合。
归并排序是分治法的经典问题。
归并排序算法的时间复杂度为O(nlogn):分的过程为logn,合的过程为n。
伪代码
MERGE(A,p,q,r)
n1=q-p+1;
n2=r-q;
create new arrays L[n1+1] and R[n2+1]
for i=0 to n1-1
L[i]=A[p+i]
for j=0 to n2-1
R[j]=A[q+1+j]
L[n1]=1000//假设1000是无穷大
R[n2]=1000
i=j=0
for k=p to r
if(L[i]<=R[j])
A[k]=L[i]
i=i+1
else
A[k]=R[j]
j=j+1
MERGE_SORT(A,p,r)
if p<r
q=floor((p+r)/2)
MERGE_SORT(A,p,q)
MERGE_SORT(A,q+1,r)
MERGE(A,p,q,r)
伪代码来源于https://blog.youkuaiyun.com/feierxiaoyezi/article/details/79998060
例
若存在序列:{7, 50, 1, 4, 32, 7, 9, 5, 25, 6},使用归并排序进行排序
(“|”表示划分)
7 50 1 4 32 7 9 5 25 6
7 50 1 4 32 | 7 9 5 25 6
7 50 | 1 4 32 | 7 9 | 5 25 6
7 | 50 | 1 4 32 | 7 9 | 5 25 6
7 | 50 | 1 | 4 32 | 7 | 9 | 5 | 25 6
7 | 50 | 1 | 4 | 32 | 7 | 9 | 5 | 25 | 6 ——不断划分直至每个子序列只有一个元素为止
7 50 | 1 4 | 7 32 | 5 9 | 6 25 ——两两合并
1 4 7 50 | 5 7 9 32 | 6 25(*具体演示如何实现该步归并)
1 4 5 7 7 9 32 50 | 6 25
1 4 5 6 7 7 9 25 32 50
对此步进行归并具体过程
(建立一个新的空序列作为排序序列,长度为两个待排序列长度之和)
(加粗表示有序序列,标记表示指针指向)
(空) 1 4 7 50 | 5 7 9 32 ——1<5,放入1
1 4 7 50 | 5 7 9 32 ——4<5,放入4
1 4 7 50 | 5 7 9 32 ——5<7,放入5
1 4 5 7 50 | 7 9 32 ——7=7,放入7(左)
1 4 5 7 50 | 7 9 32 ——7<50,放入7
1 4 5 7 7 50 | 9 32 ——9<50,放入9
1 4 5 7 7 9 50 | 32——32<50,放入32
1 4 5 7 7 9 32 50 ——放入50
1 4 5 7 7 9 32 50
即完成该步归并
gif制作来源于VisuAlgo https://visualgo.net/zh/sorting
代码
#include <iostream>
#define N 10
using namespace std;
//归并排序
void merge(int a[], int start1, int end1, int start2, int end2) {
int i = start1, j = start2;
int n = (end1 - start1 + 1) + (end2 - start2 + 1);
vector<int> temp(n);
int k = 0;
while (i <= end1 && j <= end2) {
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while (i <= end1)
temp[k++] = a[i++];
while (j <= end2)
temp[k++] = a[j++];
for (int i = 0; i < n; i++)
a[start1 + i] = temp[i];
}
void MergeSort(int a[], int start, int end) {
if (start < end) {
int mid = (start + end) >> 1;
MergeSort(a, start, mid);
MergeSort(a, mid + 1, end);
merge(a, start, mid, mid + 1, end);
}
}
int main() {
int a[N] = { 7, 50, 1, 4, 32, 7, 9, 5, 25, 6 };
int length = sizeof(a) / sizeof(a[0]);
MergeSort(a, 0, length - 1); //归并排序
for (int i = 0; i < N; i++)
cout << a[i] << " ";
cout << endl;
system("pause");
return 0;
}