文字描述
在折半插入排序的基础上进行改进, 另设一个和待排序序列L相同的数组D, 首先将L[1]赋值给D[0], 数组D中数据是已经排好序的, first指向最小值下标,final指向最大值下标。初始时,first和final值都为0。之后将L的第二个元素开始依次和D[0]比较,大于D[0]的插入到D[0]之后的序列,小于D[0]的插入到D[0]之前的序列;这里可以将数组D想象成一个循环的圆。
示意图
算法分析
时间复杂度为n*n, 辅助空间为n,是稳定的排序方法。
二路插入排序和折半插入排序比,只是可以大概率的减少移动的次数,但不能绝对避免,当待排序序列中的第一个数据就是最小值或者最大值时,2-路插入排序将完全失去它的优越性。
代码实现
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define EQ(a, b) ((a) == (b)) //数a和数b相等则为True,否则为False 5 #define LT(a, b) ((a) < (b)) //数a小于数b则为True 6 #define LQ(a, b) ((a) <= (b)) //数a小于或等于数b则为True 7 8 #define MAXSIZE 20 //待排序数的最多个数 9 typedef int KeyType; //定义待排序数据的关键字类型为int 10 typedef int InfoType; //定义待排序数据的其他信息类型为int 11 typedef struct{ 12 KeyType key; //关键字 13 InfoType otherinfo; //其他数据项 14 }RedType; //记录类型 15 16 typedef struct{ 17 RedType r[MAXSIZE+1]; //r[0]闲置或用作哨兵单元 18 int length; //顺序表长度 19 }SqList; //顺序表类型 20 21 /* 22 * 顺序打印序列表L中的关键字 23 */ 24 void PrintList(SqList L){ 25 int i = 0; 26 printf("len:%d; data:", L.length); 27 for(i=1; i<=L.length; i++){ 28 printf("%d ", L.r[i].key); 29 } 30 printf("\n"); 31 return ; 32 } 33 34 #define DEBUG 35 36 /* 37 * 2-路插入排序算法的实现 38 * 39 * @param 40 * SqList *L : 待排序的顺序表 41 */ 42 void TwoInsertSort(SqList *L) 43 { 44 //数组D是和L中关键字列表长度相同的辅助数组 45 RedType D[MAXSIZE] = {0}; 46 //将L中第一个数据存入D[0] 47 D[0] = L->r[1]; 48 49 int i = 0, j = 0, n = L->length; 50 //first表示D中最小值下标,final表示D中最大值下标 51 int first = 0, final = 0; 52 int k = 0; 53 #ifdef DEBUG 54 for(j=0; j<n; j++){ 55 printf("%d ", D[j].key); 56 } 57 printf("\nthe %d lap:fist=%d, final=%d\n\n", i, first, final); 58 #endif 59 60 for(i=2; i<=L->length; i++){ 61 if(LT(L->r[i].key, D[first].key)){ 62 // 待插入元素比最小的元素小 63 first = (first-1+n)%n; 64 D[first] = L->r[i]; 65 }else if(LT(D[0].key, L->r[i].key)){ 66 // 待插入元素比最大的元素大 67 final = (final+1)%n; 68 D[final] = L->r[i]; 69 }else{ 70 // 待插入元素处在最小元素和最大元素中间 71 // 采用直接插入排序的方法,插入到数组D中合适的位置 72 k = (final+1)%n; 73 while(LT(L->r[i].key, D[(k-1+n)%n].key)){ 74 D[(k+n)%n] = D[(k-1+n)%n]; 75 k = (k-1+n)%n; 76 } 77 D[(k+n)%n] = L->r[i]; 78 final = (final+1)%n; 79 } 80 #ifdef DEBUG 81 for(j=0; j<n; j++){ 82 printf("%d ", D[j].key); 83 } 84 printf("\nthe %d lap:fist=%d, final=%d\n\n", i, first, final); 85 #endif 86 } 87 //将排序记录复制到原来的顺序表里 88 for(j=0; j<n; j++){ 89 L->r[1+j] = D[first]; 90 first = (first+1)%n; 91 } 92 } 93 94 int main(int argc, char *argv[]) 95 { 96 if(argc < 2){ 97 return -1; 98 } 99 SqList L; 100 int i = 0; 101 for(i=1; i<argc; i++){ 102 if(i>MAXSIZE) 103 break; 104 L.r[i].key = atoi(argv[i]); 105 } 106 L.length = (i-1); 107 108 TwoInsertSort(&L); 109 PrintList(L); 110 return 0; 111 }
运行
[jennifer@localhost Data.Structure]$ ./a.out 12 5 7 4 5 3 45 76
12 0 0 0 0 0 0 0
the 0 lap:fist=0, final=0
12 0 0 0 0 0 0 5
the 2 lap:fist=7, final=0
7 12 0 0 0 0 0 5
the 3 lap:fist=7, final=1
7 12 0 0 0 0 4 5
the 4 lap:fist=6, final=1
5 7 12 0 0 0 4 5
the 5 lap:fist=6, final=2
5 7 12 0 0 3 4 5
the 6 lap:fist=5, final=2
5 7 12 45 0 3 4 5
the 7 lap:fist=5, final=3
5 7 12 45 76 3 4 5
the 8 lap:fist=5, final=4
len:8; data:3 4 5 5 7 12 45 76
[jennifer@localhost Data.Structure]$