题目:给出一个数组,数组中的两半都是已知顺序的,现要实现将这个数组有序化,要求空间复杂度为 O(1),时间复杂度尽可能的小,编程实现!
#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;如上程序代码理解~~~