二路归并排序(非递归实现)

归并排序是一种借助”归并“进行排序的方法。

归并的含义是将两个或两个以上的有序序列归并为一个有序序列的过程。归并排序的主要思想是:将若干有序序列逐步归并,最终归并为一个有序序列。

其中最常见的是二路归并排序。

二路归并排序是一种稳定的排序方法,其基本思想是:将若干个有序序列两两归并,直到形成一个有序序列为止。

方法如下:将一个长度为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 }

 

转载于:https://www.cnblogs.com/magicalzh/p/7844315.html

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用C++实现二路归并、递归的归并排序非递归归并排序的代码示例: 1. 二路归并排序: ```cpp #include <iostream> using namespace std; void merge(int arr[], int left[], int leftSize, int right[], int rightSize) { int i = 0, j = 0, k = 0; while (i < leftSize && j < rightSize) { if (left[i] <= right[j]) { arr[k++] = left[i++]; } else { arr[k++] = right[j++]; } } while (i < leftSize) { arr[k++] = left[i++]; } while (j < rightSize) { arr[k++] = right[j++]; } } void mergeSort(int arr[], int size) { if (size <= 1) { return; } int mid = size / 2; int left[mid]; int right[size - mid]; for (int i = 0; i < mid; i++) { left[i] = arr[i]; } for (int i = mid; i < size; i++) { right[i - mid] = arr[i]; } mergeSort(left, mid); mergeSort(right, size - mid); merge(arr, left, mid, right, size - mid); } int main() { int arr[] = {5, 2, 8, 3, 1}; int size = sizeof(arr) / sizeof(arr[0]); mergeSort(arr, size); cout << "Sorted array: "; for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ``` 2. 递归的归并排序: ```cpp #include <iostream> using namespace std; void merge(int arr[], int left[], int leftSize, int right[], int rightSize) { int i = 0, j = 0, k = 0; while (i < leftSize && j < rightSize) { if (left[i] <= right[j]) { arr[k++] = left[i++]; } else { arr[k++] = right[j++]; } } while (i < leftSize) { arr[k++] = left[i++]; } while (j < rightSize) { arr[k++] = right[j++]; } } void mergeSort(int arr[], int size) { if (size <= 1) { return; } int mid = size / 2; int left[mid]; int right[size - mid]; for (int i = 0; i < mid; i++) { left[i] = arr[i]; } for (int i = mid; i < size; i++) { right[i - mid] = arr[i]; } mergeSort(left, mid); mergeSort(right, size - mid); merge(arr, left, mid, right, size - mid); } int main() { int arr[] = {5, 2, 8, 3, 1}; int size = sizeof(arr) / sizeof(arr[0]); mergeSort(arr, size); cout << "Sorted array: "; for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ``` 3. 非递归归并排序: ```cpp #include <iostream> using namespace std; void merge(int arr[], int left[], int leftSize, int right[], int rightSize) { int i = 0, j = 0, k = 0; while (i < leftSize && j < rightSize) { if (left[i] <= right[j]) { arr[k++] = left[i++]; } else { arr[k++] = right[j++]; } } while (i < leftSize) { arr[k++] = left[i++]; } while (j < rightSize) { arr[k++] = right[j++]; } } void mergeSort(int arr[], int size) { for (int currSize = 1; currSize <= size - 1; currSize = 2 * currSize) { for (int leftStart = 0; leftStart < size - 1; leftStart += 2 * currSize) { int mid = min(leftStart + currSize - 1, size - 1); int rightEnd = min(leftStart + 2 * currSize - 1, size - 1); int left[currSize]; int right[rightEnd - mid]; for (int i = 0; i < currSize; i++) { left[i] = arr[leftStart + i]; } for (int i = 0; i < rightEnd - mid; i++) { right[i] = arr[mid + 1 + i]; } merge(arr, left, currSize, right, rightEnd - mid); } } } int main() { int arr[] = {5, 2, 8, 3, 1}; int size = sizeof(arr) / sizeof(arr[0]); mergeSort(arr, size); cout << "Sorted array: "; for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值