内部排序->插入排序->其它插入排序->表插入排序

文字描述

  和之前的插入排序比,表插入排序可以保证排序过程中不移动记录;因此表插入排序所用的存储结构和之前的顺序存储不同,表插入排序采用静态链表类型作为待排记录序列的存储结构,设数组中下标0的分量为表头结点,并令表头结点记录的关键字取最大整数MAXINT。表插入排序的基本操作仍然是将一个记录插入到已经排好序的有序表中,和直接插入排序有相似之处,不同之处在于是以修改2次指针值代替1次移动记录。

示意图

 

算法分析

  时间复杂度仍然是n*n, 因为排序过程中需要和数据个数相同的指针值,所以辅助空间为n,是稳定的排序方法。

 

代码实现

见附录1

 


 

  另外, 与表插入排序相关的还有一个重排算法,  先依旧从文字描述, 示意图, 复杂度和代码实现四方面分析该算法.

文字描述

       表插入排序的结果只是求得一个有序链表,则只能对它进行顺序查找, 不能进行随机查找. 为了能实现有序表的折半查找,尚需对记录进行重新排列.

       重排记录的做法是: 顺序扫描有序链表, 将链表中第i个结点移动至数组的第i个分量重. 若第i个最小关键字的结点是数组中下标为p且p>i的分量,则互换SL.r[i]和SL.r[p],且令SL.r[i]中指针域的值改为p; 由于此时数组中所有小于i的分量中已经是“到位”的分量,则当p<i时,应顺链继续查找直到p>i或p==i为止。

 

示意图

 

算法分析

在重排记录的过程中,最坏情况是每个记录到位都必须进行一次记录的交换,即3次移动记录,所以重排记录至多需进行3(n-1)次记录的移动, 它并不增加表插入排序的时间复杂度,还是n*n, 辅助空间为1

代码实现

见附录1

 


 

附录1

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 #define DEBUG
  5 
  6 //静态链表容量
  7 #define SIZE 100
  8 //最大整数
  9 #define MAX  100
 10 
 11 #define EQ(a, b) ((a) == (b))
 12 #define LT(a, b) ((a) <  (b))
 13 #define LQ(a, b) ((a) <= (b))
 14 
 15 //定义关键字类型为整数类型
 16 typedef int KeyType;
 17 //定义其它数据项为整数类型
 18 typedef int InfoType;
 19 
 20 //记录类型
 21 typedef struct{
 22     //关键字项
 23     KeyType key;
 24     //其他数据项
 25     InfoType otherinfo;
 26 }RedType;    
 27 
 28 //表结点类型
 29 typedef struct{
 30     //记录项
 31     RedType rc;
 32     //指针项
 33     int next;
 34 }SLNode;
 35 
 36 //静态链表类型
 37 typedef struct{
 38     //0号单元为表头结点
 39     SLNode r[SIZE];
 40     //链表当前长度
 41     int length;
 42 }SLinkListType;
 43 
 44 //顺序打印静态链表中的关键字和指向下个数据的指针
 45 void PrintSList(SLinkListType SL){
 46     int i = 0;
 47     printf("下标值:");
 48     for(i=0; i<=SL.length; i++){
 49         printf("[%d]  ", i);
 50     }
 51     printf("\n关键字:");
 52     for(i=0; i<=SL.length; i++){
 53         printf(" %-4d", SL.r[i].rc.key);
 54     }
 55     printf("\n其他值:");
 56     for(i=0; i<=SL.length; i++){
 57         printf(" %-4c", SL.r[i].rc.otherinfo);
 58     }
 59     printf("\n\n");
 60     return ;
 61 }
 62 
 63 //表插入排序算法
 64 void TableInsertSort(SLinkListType *SL)
 65 {
 66     //0号位表头结点,存最大整数值MAX
 67     SL->r[0].rc.key = MAX;
 68     //首先将静态链表中数组下标为1的分量和表头结点构成一个循环链表
 69     SL->r[0].next = 1;
 70     SL->r[1].next = 0;
 71 
 72     //和直接插入排序相似,只是不移动记录,只是改变指针指
 73     int i = 0, q = 0, p = 0;
 74     for(i=2; i<=SL->length; i++){
 75         q = 0;
 76         p = SL->r[q].next;
 77         while(LQ(SL->r[p].rc.key, SL->r[i].rc.key)){
 78             q = p;
 79             p = SL->r[q].next;
 80         }
 81         //以修改2次指针值代替移动记录
 82         SL->r[q].next = i;
 83         SL->r[i].next = p;
 84     }
 85     return ;
 86 }
 87 
 88 /*
 89  * 表插入排序相关的重排算法
 90  *
 91  * 根据静态链表SL中各结点的指针调整记录位置,
 92  * 使得SL中各记录按关键字升序排序
 93  *
 94  */
 95 void Arrange(SLinkListType *SL)
 96 {
 97     //p指示第一个记录的当前位置
 98     int p = SL->r[0].next, q = 0;
 99     int i = 0;
100     SLNode tmp;
101 
102     //SL.r[1..i-1]中记录已按关键字有序排列
103     for(i=1; i<SL->length; ++i){
104         //第i个记录的在SL中的当前位置应不小于i
105         while(p<i){
106             p = SL->r[p].next;
107         }
108         //q指示尚未调整的表尾
109         q = SL->r[p].next;
110         if(p != i){
111             //交换记录,使第i个记录到位
112             tmp = SL->r[p];
113             SL->r[p] = SL->r[i];
114             SL->r[i] = tmp;
115             //指向被移走的记录,使得以后可由while循环找回
116             SL->r[i].next = p;
117         }
118         //p指示尚未调整的表尾,为找第i+1个记录作准备
119         p = q;
120 #ifdef DEBUG
121         printf("第%d趟重排:\n", i);
122         PrintSList(*SL);
123 #endif
124     }
125 }
126 
127 int main(int argc, char *argv[])
128 {
129     if(argc < 2){
130         return -1;
131     }
132     SLinkListType SL;
133     int i = 0;
134     for(i=1; i<argc; i++){
135         if(i>SIZE)
136             break;
137         SL.r[i].rc.key = atoi(argv[i]);
138         SL.r[i].next = 0;
139         SL.r[i].rc.otherinfo = 'a'+i-1;
140     }
141     SL.length = (i-1);
142     SL.r[0].rc.key = 0;
143     SL.r[0].rc.otherinfo = '0';
144     /*进行表插入排序*/
145     TableInsertSort(&SL);
146     printf("表插入排序之后的静态链表:\n");
147     PrintSList(SL);
148 
149     /*重排记录,使它能满足有序表的折半查找*/
150     Arrange(&SL);
151     return 0;
152 }
表插入排序和重排算法

 

运行

 

 

posted on 2018-07-21 19:03  LiveWithACat  阅读(314)  评论(0编辑  收藏  举报