这次要谈的插入排序算法就是2-路插入排序,2-路插入算法是在折半插入排序的基础上改进
它的目的就是想减少数据的移动次数,因此,另外开辟辅助空间。首先开辟一个长度为iLength的临时数组,将待排序数组的第1个元素放到临时数组的第0位,作为初始化。书中的意思是将该值作为每次排序的参照,大于等于这个参照值就后插,小于参照值就前插。同时定义两个游标first和final分别指向临时数组当前最小值和最大值所在位置。算法思路就是这样,但是在网上看了些实现好的算法,发现并不是完全按照这个思路。况且书中P262给出了排序示例,按照网上给出,完全达不到这种效果,于是本人索性就自己实现了下。当然这里还是给出两种,一种是网上找到的比较多的。闲话少说,贴代码,上图。
1)2-路插入排序算法实现
int TwoInsertSort()
{
int final = 0;
int first = 0;
const int iLenght = iCount -1;
int iTempBuff[iLenght] = {0};
iTempBuff[0] = iRawBuff[1];
for (int i = 2; i <= iLenght;i++)
{
if(iRawBuff[i] > iTempBuff[final])
{
//大于当前最大值,后插
final++;
iTempBuff[final] = iRawBuff[i];
}
if(iRawBuff[i]< iTempBuff[first])
{
//小于当前最小值,前插
first = (first-1+iLenght)%iLenght;
iTempBuff[first] = iRawBuff[i];
}
if(iRawBuff[i] < iTempBuff[final]&&iRawBuff[i] > iTempBuff[first])
{
//大于当前最小值,小于当前最大值,中间插
int j = final++;
while (iRawBuff[i] < iTempBuff[j])
{
iTempBuff[(j+1)%iLenght] = iTempBuff[j];
j = (j-1+iLenght)%iLenght;
}
iTempBuff[j+1] = iRawBuff[i];
}
printf("第%d趟:\n",i-1);
for(int k = 0; k < iLenght; k++)
{
std::cout<<iTempBuff[k]<<"\t";
}
std::cout<<std::endl;
}
//导入输入到原始数组中
for (int k = 0; k < iLenght; k++)
{
iRawBuff[k+1] = iTempBuff[(first++)%iLenght];
}
return 0;
}
可以看出,以这种方式进行排序的流程和书的给出的每趟排序的序列不同。主要是从插入“27”开始不同的。
下面给出本人修改后的算法(本人喜欢钻牛角尖,就是为了和书上的例子完全吻合,先不谈性能,只追求一致性)。
首先讲下思路:这里面“49”就是所谓的参照值,那么按照算法描述,每次有新的插入时候,为了实现所谓的两路,均需要和参照值进行比较。当然上面的实现也做到了两路,但是在数据的移动上有不同,就是参照值的位置有了变化。本算法的目的就是保证参照值位置不变,因此对于每个待排序的值,第一步就是和参照值进行比较,从而决定是前插还是后插。相当于划分了两个一端固定的区间。思路就是这样,本着负责的态度,上代码,贴图。
2)改进2-路插入排序算法实现
int ChangeTwoInsertSort()
{
//ehance the two insert sort
int final = 0;
int first = 0;
const int iLenght = iCount -1;
int iTempBuff[iLenght] = {0};
iTempBuff[0] = iRawBuff[1];
//先和temp[0]比较从而以其为分界线
for (int i = 2; i <= iLenght; i++ )
{
if (iRawBuff[i] >= iTempBuff[0])
{
//that means ,输入右半部
if (iRawBuff[i] >=iTempBuff[final])
{
//大于当前最大值
final++;
iTempBuff[final] = iRawBuff[i];
}
else
{
//小于当前最大值,但大于分界线值,左移,但不超过零
int j = final++;
while ((iTempBuff[j]>=iRawBuff[i])&&(j>=0))
{
iTempBuff[j+1] = iTempBuff[j];
j--;
}
iTempBuff[j+1] = iRawBuff[i];
}
}
if (iRawBuff[i] < iTempBuff[0])
{
//that means 输入左半部
if (iRawBuff[i] >= iTempBuff[first])
{
//
int j = first--;
while (j<=iLenght&&iTempBuff[j]<=iRawBuff[i])
{
iTempBuff[j-1] = iTempBuff[j];
j++;
}
iTempBuff[j-1] = iRawBuff[i];
}
if (iRawBuff[i] < iTempBuff[first])
{
//小于当前最小
first = (first-1+iLenght)%iLenght;
iTempBuff[first] = iRawBuff[i];
}
}
printf("第%d趟:\n",i);
for(int k = 0; k < iLenght; k++)
{
std::cout<<iTempBuff[k]<<"\t";
}
std::cout<<"\n";
}
//数据导入原始数组
for(int i = 0; i< iLenght; i++)
{
iRawBuff[i+1] = iTempBuff[(first++)%iLenght];
}
return 0;
}