2-路插入排序是在折半插入排序的基础上进行的改进,目的是减少排序过程中记录移动的次数。
算法的思想为:另设一个和原始待排序列L相同的数组D,首先将L[1]复制给D[1],并把D[1]看成是已排好序的序列中处于中间位置的元素,之后将L中的从第二个元素开始依次插入到数组D中,大于D[1]的插入到D[1]之后的序列(此处我称为右半边序列,用的是数组左半部分空间),小于D[1]的插入到D[1]之前的序列(左半边序列,用的是数组右半部分空间)。
2-路插入排序简单的说是以待排序序列中第一个记录为标准将序列分为两部分:小于该记录值的部分和大于该记录值的部分,两个部分都使用折半插入排序来完成排序。
注意:当L[1]中的记录值最小时,2-路插入排序失去它的优越性,等同于折半插入排序
时间复杂度:o(N*N/8)
空间复杂度o(N)
#include<iostream>
#include<vector>
using namespace std;
void BinInsertSort(vector<int> ivec,vector<int> &ivec1){
int first,final,i,j,low1,high1,mid1,low2,mid2,high2,flag=1;
first=final=0; //first记录右半边序列的第一个元素的下标,final记录左半边序列的最后一个元素的下标
for(i=1;i<ivec.size();i++){
if(ivec[i]>ivec1[0]){
low1=0;
high1=final;
while(low1<=high1){
mid1=(low1+high1)/2;
if(ivec[i]<ivec1[mid1])
high1=mid1-1;
else
low1=mid1+1;
}
for(j=final;j>=high1+1;j--)
ivec1[j+1]=ivec1[j]; //左半边序列右移,腾出待插元素的位置
ivec1[high1+1]=ivec[i];
final++;
}else{
if(flag==1){
first=ivec1.size()-1;
ivec1[first]=ivec[i];
flag++;
}else{
low2=first;
high2=ivec1.size()-1;
while(low2<=high2){
mid2=(low2+high2)/2;
if(ivec[i]<ivec1[mid2])
high2=mid2-1;
else
low2=mid2+1;
}
for(j=first;j<high2+1;j++)
ivec1[j-1]=ivec1[j]; //右半边序列左移,腾出待插元素的位置
ivec1[high2]=ivec[i];
first--;
}
}
}
cout<<"排序之后的序列为:";
if(first!=0){ //first为0时表示,待排序序列仅仅进行了左半边的排序,即第一个元素是序列中最小的
for(i=first;i<=ivec1.size()-1;i++)
cout<<ivec1[i]<<" ";
for(i=0;i<=final;i++)
cout<<ivec1[i]<<" ";
cout<<endl;
}else{
for(i=0;i<=final;i++)
cout<<ivec1[i]<<" ";
cout<<endl;
}
}
void main(){
vector<int> ivec;
vector<int>::iterator iter;
int v;
cout<<"请输入待排序的序列:";
while(cin>>v){
ivec.push_back(v);
}
vector<int> ivec1(ivec);
cout<<"排序之前的序列为:";
for(iter=ivec1.begin();iter!=ivec1.end();iter++)
cout<<*iter<<" ";
cout<<endl;
BinInsertSort(ivec,ivec1);
}