2-路插入排序
一、定义
2-路插入排序是在折半插入排序的基础上再改进,其目的是减少排序过程中移动记录的次数,但为此要付出n个记录的辅助空间。
二、具体实现
另设一个同类型的数组d,先将list[0]复制给d[0],并将d[0]看成是排好序的序列中处于中间位置的记录,然后从list中第二个记录起依次插入到d[0]之前或之后的有序序列中。先将待插入记录和d[0]进行比较,若大于d[0],则插入d[0]后的有序表中,反之,则插入d[0]之前的有序表中。可以将d看成是一个循环量,并设置first和final指针分别指向有序表中第一个和最后一个记录的位置。
移动记录约为n^2 / 8,因此,2-路插入排序只能减少移动记录次数,而不能绝对避免移动记录。并且,当list[1]是待排序记录中最大或最小的记录时,2-路插入排序就完全失去它的优越性。
void twoinsert_sort(ElementType list[],int n){
int i,j,first,final;
ElementType *d = (ElementType *)malloc(sizeof(ElementType) * n);
if(d != NULL){
d[0] = list[0];//以d[0]作为界限,位置一直不变,d看作循环向量
first = final = 0;
for(i = 1; i < n ;i++){
//插入右边区域
if(list[i] >= d[0]){
if(list[i] >= d[final])//插入值的大于最大值
d[++final] = list[i];
else{
//插入值位于最大值和中间值之间,向后移
for(j = final;j > 0 && d[j] >= list[i];j--) d[j + 1] = d[j];
d[j] = list[i];
final++;
}
}else{
//插入左边区域
//小于当前最小
if(list[i] <= d[first]){
first = (n + first - 1) % n;
d[first] = list[i];
}else{
//插入值位于最小值和中间值之间,向前移
first--; //先--,确定first位置
for(j = first + 1; j < n && d[j] <= list[i] ;j++) d[j - 1] = d[j];
d[j - 1] = list[i];
}
}
}
//复制
for(i = 0; i < n ;i++){
list[i] = d[(first++) % n];
}
//释放辅助空间
free(d);
d = NULL;
}
}