c++原地归并排序变形实例源码



c++原地归并排序变形。

题目:给出一个数组,数组中的两半都是已知顺序的,现要实现将这个数组有序化,要求空间复杂度为 O(1),时间复杂度尽可能的小,编程实现!

 

 

  1. #include <iostream>
  2. using namespace std;
  3. int arr[10] = { 1,3,5,7,9,2,4,6,8,10};
  4. //交换数据
  5. int swaparr(int &a,int &b)
  6. {
  7.     a=a+b;
  8.     b=a-b;
  9.     a=a-b;
  10. }
  11. void reversearr(int a[],int n)  //数组起始地址,数组长度
  12. {
  13.     int i,b;
  14.     for(i=0,b=n-1;i<b;i++,b–)
  15.         swaparr(a[i],a[b]);
  16. }
  17. void leftshift(int a[],int n,int i)//数组以a[0]为起始地址,长度为n,循环左移i位
  18. {
  19.     reversearr(a,i);
  20.     reversearr(a+i,n-i);
  21.     reversearr(a,n);
  22. }
  23. void mergesort(int a[],int n,int s)//数组,总元素,第二段的起始地址
  24. {
  25.     int mid = s;//记录第一段数组的最后一位
  26.     int i,j;//两个移动指针
  27.     i=0;
  28.     j=s;
  29.     while(true)
  30.     {
  31.         while(a[i]<=a[j] && i<mid)
  32.             i++;
  33.         while(a[j]<a[i] && j<n)
  34.             j++;
  35.         if(i >= mid)  //  出口1
  36.             break;
  37.         ///针对 i~j-1 位置的几个数实现循环左移 j-s位
  38.         leftshift(a+i,j-i,mid-i);
  39.         i=j-mid+i;//重新计算出 i 的位置
  40.         //重新计算出mid的位置
  41.         mid=j;
  42.         if(mid>=n)        //出口2
  43.             break;
  44.     }
  45. }
  46. void print()
  47. {
  48.     int i=0;
  49.     for(i=0;i<10;i++)
  50.         cout<<arr[i]<<”  ”;
  51.     cout<<endl;
  52. }
  53. int main()
  54. {
  55.     cout << ”Hello world!” << endl;
  56.     print();
  57.     mergesort(arr,10,5);
  58.     print();
  59.     return 0;
  60. }

 

 


说明:

此处由于要求空间复杂度为O(1),不能使用另开辟空间的归并排序实现,这里我们需要在原有数组中实现归并排序,原地归并排序;

首先,我们很容易理解到可以使用插入排序的方法将 数组后半段数据通过插入排序使整个数组归并在一起;这个最坏情况下的时间复杂度是O(n2);

比如 {6,7,8,9,10,1,2,3,4,5};这个数组将后5个使用插入排序的话时间复杂度为O(n2);为了解决这种情况,次我们提出了更好的解法:

对于数组arr[10] ,两半的起始指针分别为 i,j;如上程序代码理解~~~