二路归并排序是一种稳定的排序方法。时间复杂度为O(nlogn),空间复杂度为O(n)。
归并排序是一种借助”归并“进行排序的方法。
归并的含义是将两个或两个以上的有序序列归并为一个有序序列的过程。归并排序的主要思想是:将若干有序序列逐步归并,最终归并为一个有序序列。
其中最常见的是二路归并排序。
二路归并排序是一种稳定的排序方法,其基本思想是:将若干个有序序列两两归并,直到形成一个有序序列为止。
方法如下:将一个长度为n的无序序列看作是n个长度为1的有序序列的集合。然后两两归并,直到整个序列有序。
在归并的过程中,可能会破坏原序列的有序性,所以需要一个新的数组在存储归并后的结果。
一次归并的算法是从开始同时遍历两个序列,将较小的值放入结果序列中,直到遍历结束,成为一个有序序列。
代码如下:
1 void Merge(int r[],int r1[],int s,int m,int t)
2 {
3 int i=s,j=m+1,k=s;
4 while(i<=m&&j<=t)
5 {
6 if(r[i]<=r[j])
7 {
8 r1[k]=r[i];
9 i++;
10 k++;
11 }
12 else
13 {
14 r1[k]=r[j];
15 j++;
16 k++;
17 }
18 }
19 if(i<=m)
20 {
21 while(i<=m)
22 {
23 r1[k]=r[i];
24 i++;
25 k++;
26 }
27 }
28 else
29 {
30 while(j<=t)
31 {
32 r1[k]=r[j];
33 j++;
34 k++;
35 }
36 }
37 }
然后,一趟遍历只需要不断调用一次归并的算法就可以实现了。
1 void MergePass(int r[] ,int r1[] , int n, int h)
2 {
3 int i=1;
4 while(i<=n-2*h+1)
5 {
6 Merge(r,r1,i,i+h-1,i+2*h-1);
7 i+=2*h;
8 }
9 if(i<n-h+1) Merge(r,r1,i,i+h-1,n);
10 else for(int k=i; k<=n; k++)
11 {
12 r1[k]=r[k];
13 }
14 }
开始时,有序序列长度为1,结束时,有序序列长度为n,所以,可以用有序序列的长度来控制排序的结束时刻。同时,排序次数为奇数时,还需要将辅助数组中的值放回原数组。
下面给出归并排序非递归算法:
1 void MergeSort(int r[],int r1[], int n)
2 {
3 int h=1;
4 while(h<n)
5 {
6 MergePass(r,r1,n,h);
7 h*=2;
8 MergePass(r1,r,n,h);
9 h*=2;
10 }
11 }
时间复杂度与空间复杂度分析
对于二路归并排序来说,它的时间复杂度比较直观,运行一趟需要扫描数据一次,一趟的时间复杂度为O(n)。整个归并排序需要运行[log2n]趟。所以,总体的时间复杂度为O(nlogn)。
对于空间复杂度,在排序时,算法使用了一个与待排序序列等长的辅助空间来存放结果,所以其空间复杂度为O(n)。
所以说,二路归并排序是一种稳定的排序方法,它的最好、最坏、平均的时间复杂度相等。
下面给出完整代码:
1 #include<iostream>
2 using namespace std;
3
4 void Merge(int r[],int r1[],int s,int m,int t)
5 {
6 int i=s,j=m+1,k=s;
7 while(i<=m&&j<=t)
8 {
9 if(r[i]<=r[j])
10 {
11 r1[k]=r[i];
12 i++;
13 k++;
14 }
15 else
16 {
17 r1[k]=r[j];
18 j++;
19 k++;
20 }
21 }
22 if(i<=m)
23 {
24 while(i<=m)
25 {
26 r1[k]=r[i];
27 i++;
28 k++;
29 }
30 }
31 else
32 {
33 while(j<=t)
34 {
35 r1[k]=r[j];
36 j++;
37 k++;
38 }
39 }
40 }
41
42 void MergePass(int r[] ,int r1[] , int n, int h)
43 {
44 int i=1;
45 while(i<=n-2*h+1)
46 {
47 Merge(r,r1,i,i+h-1,i+2*h-1);
48 i+=2*h;
49 }
50 if(i<n-h+1) Merge(r,r1,i,i+h-1,n);
51 else for(int k=i; k<=n; k++)
52 {
53 r1[k]=r[k];
54 }
55 }
56
57 void MergeSort(int r[],int r1[], int n)
58 {
59 int h=1;
60 while(h<n)
61 {
62 MergePass(r,r1,n,h);
63 h*=2;
64 MergePass(r1,r,n,h);
65 h*=2;
66 }
67 }
68
69 int main()
70 {
71 int a[10000];
72 int a1[10000];
73 int n;
74 cin>>n;
75 for(int i=1;i<=n;i++) cin>>a[i];
76 MergeSort(a,a1,n);
77 for(int i=1;i<=n;i++) cout<<a[i]<<" ";
78 cout<<endl;
79 return 0;
80 }