c++原地归并排序变形。
题目:给出一个数组,数组中的两半都是已知顺序的,现要实现将这个数组有序化,要求空间复杂度为 O(1),时间复杂度尽可能的小,编程实现!
[cpp] view plaincopy
- #include <iostream>
- using namespace std;
- int arr[10] = { 1,3,5,7,9,2,4,6,8,10};
- //交换数据
- int swaparr(int &a,int &b)
- {
- a=a+b;
- b=a-b;
- a=a-b;
- }
- void reversearr(int a[],int n) //数组起始地址,数组长度
- {
- int i,b;
- for(i=0,b=n-1;i<b;i++,b–)
- swaparr(a[i],a[b]);
- }
- void leftshift(int a[],int n,int i)//数组以a[0]为起始地址,长度为n,循环左移i位
- {
- reversearr(a,i);
- reversearr(a+i,n-i);
- reversearr(a,n);
- }
- void mergesort(int a[],int n,int s)//数组,总元素,第二段的起始地址
- {
- int mid = s;//记录第一段数组的最后一位
- int i,j;//两个移动指针
- i=0;
- j=s;
- while(true)
- {
- while(a[i]<=a[j] && i<mid)
- i++;
- while(a[j]<a[i] && j<n)
- j++;
- if(i >= mid) // 出口1
- break;
- ///针对 i~j-1 位置的几个数实现循环左移 j-s位
- leftshift(a+i,j-i,mid-i);
- i=j-mid+i;//重新计算出 i 的位置
- //重新计算出mid的位置
- mid=j;
- if(mid>=n) //出口2
- break;
- }
- }
- void print()
- {
- int i=0;
- for(i=0;i<10;i++)
- cout<<arr[i]<<” ”;
- cout<<endl;
- }
- int main()
- {
- cout << ”Hello world!” << endl;
- print();
- mergesort(arr,10,5);
- print();
- return 0;
- }
说明:
此处由于要求空间复杂度为O(1),不能使用另开辟空间的归并排序实现,这里我们需要在原有数组中实现归并排序,原地归并排序;
首先,我们很容易理解到可以使用插入排序的方法将 数组后半段数据通过插入排序使整个数组归并在一起;这个最坏情况下的时间复杂度是O(n2);
比如 {6,7,8,9,10,1,2,3,4,5};这个数组将后5个使用插入排序的话时间复杂度为O(n2);为了解决这种情况,次我们提出了更好的解法:
对于数组arr[10] ,两半的起始指针分别为 i,j;如上程序代码理解~~~