插入排序:将待排序元素分为已排序子集和未排序子集,一次从未排序子集中的一个元素插入已排序子集中,使已排序自己仍然有序;重复执行以上过程,指导所有元素都有序为止。
2-路插入排序是在折半插入排序的基础上再改进,其目的是减少排序过程中移动记录的次数,但为此需要n个记录的辅助空间。
基本算法思想:另设一个与L.r同类型的数组d,首先将L.r[1]赋值给d[1],并将d[1]看成是在排好序的序列中处于中间位置的记录,然后从L.r中的第2个记录起依次插入到d[1]之前或之后的有序序列中。先将待插记录的关键字和d[1]的关键字进行比较,若 L.r[i].key<d[1].key ,则将L.r[i]插入到d[1]之前的有序表中;反之,则将L.r[i]插入到d[1]之后的有序表中。在实现算法时,可将d看成是一个循环向量,并设两个指针first和final分别指示排序过程中得到的有序序列中的第一个记录和最后一个记录在d中的位置。
在2-路插入排序中,移动记录的次数约为 n2/8 。因此,2-路插入排序只能减少移动记录的次数,而不能绝对避免移动记录。并且,当L.data[1]是带排序记录中关键字最小或最大的记录时,2-路插入排序完全失去它的优越性。因此,若希望在排序过程中不移动记录,只有改变存储结构,进行表插入排序。
- 类型定义头文件
#define MAXSIZE 20 /* 一个用作示例的小顺序表的最大长度 */
typedef int InfoType; /* 定义其它数据项的类型 */
typedef int KeyType; /* 定义关键字类型为整型 */
typedef struct
{
KeyType key; /* 关键字项 */
InfoType otherinfo; /* 其它数据项,具体类型在主程中定义 */
}RedType; /* 记录类型 */
typedef struct
{
RedType r[MAXSIZE+1]; /* r[0]闲置或用作哨兵单元 */
int length; /* 顺序表长度 */
}SqList; /* 顺序表类型 */
- 2-路插入排序函数
void P2_InsertSort(SqList *L)
{ /* 2_路插入排序 */
int i,j,first,final;
RedType *d;
d=(RedType*)malloc((*L).length*sizeof(RedType)); /* 生成L.length个记录的临时空间 */
d[0]=(*L).r[1]; /* 设L的第1个记录为d中排好序的记录(在位置[0]) */
first=final=0; /* first、final分别指示d中排好序的记录的第1个和最后1个记录的位置 */
for(i=2;i<=(*L).length;++i)
{ /* 依次将L的第2个~最后1个记录插入d中 */
if ((*L).r[i].key<d[first].key)
{ /* 待插记录小于d中最小值,插到d[first]之前(不需移动d数组的元素) */
first=(first-1+(*L).length)%(*L).length; /* 设d为循环向量 */
d[first]=(*L).r[i];
}
else if((*L).r[i].key>d[final].key)
{ /* 待插记录大于d中最大值,插到d[final]之后(不需移动d数组的元素) */
final=final+1;
d[final]=(*L).r[i];
}
else
{ /* 待插记录大于d中最小值,小于d中最大值,插到d的中间(需要移动d数组的元素) */
j=final++; /* 移动d的尾部元素以便按序插入记录 */
while((*L).r[i].key<d[j].key)
{
d[(j+1)%(*L).length]=d[j];
j=(j-1+(*L).length)%(*L).length;
}
d[j+1]=(*L).r[i];
}
}
for(i=1;i<=(*L).length;i++) /* 把d赋给L.r */
(*L).r[i]=d[(i+first-1)%(*L).length]; /* 线性关系 */
}
- 主程序
#define N 8
void print(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
printf("(%d,%d)",L.r[i].key,L.r[i].otherinfo);
printf("\n");
}
void main()
{
RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}};
SqList l;
int i;
for(i=0;i<N;i++) /* 给l1.r赋值 */
l.r[i+1]=d[i];
l.length=N;
printf("排序前:\n");
print(l);
P2_InsertSort(&l);
printf("2_路插入排序后:\n");
print(l);
}