直接插入排序
直接插入排序的基本思想:将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录增长1的有序表。
以顺序表L = {0,5,3,4,6,2}为例,length = 5,参与排序的纪录为r[1]~r[5],r[0]充当哨兵(中间变量),协助排序的进行。代码如下所示:
1 //将一个记录插入到已经排好序的有序表中
2 //L->r[0]当作哨兵
3 void InsertSort(SqList* L)
4 {
5 int i, j;
6
7 //i从2开始,假设r[1]已经放好了位置
8 //需要将每个记录都插入到正确的位置,故i <= length
9 for (i = 2; i <= L->length; i++)
10 {
11 //将r[i]插入到已经排好序的有序表中
12 //若不满足if条件,则说明不需要进行插入,不需要改变其位置
13 //若满足if条件,则说明需要将r[i]插入到r[i-1]前面
14 if (L->r[i] < L->r[i - 1])
15 {
16 L->r[0] = L->r[i]; //将需要插入有序表的记录r[i]放到r[0]的位置
17
18 //将已经排好序的有序表中大于r[i]的元素右移一位
19 //j=i-1;从第i个元素前面的一个元素开始从后往前根据条件执行右移
20 //一定会出现r[j] > r[0]不满足的情况(当j=0时),从而跳出循环
21 //所以不需要判断j是否小于0
22 for (j = i - 1; L->r[j] > L->r[0]; j--)//从后往前一个一个右移
23 L->r[j + 1] = L->r[j];
24
25 L->r[j + 1] = L->r[0];//将r[i]插入到空出来的位置,即正确的位置
26 }
27 }
28 }
顺序表中的记录变化如下所示:
(注意:图中的 “=” 是相等的意思,是经过代码中赋值语句之后的结果,不是赋值的意思)
当满足if条件时,即r[i] < r[i-1],说明对于一个已经排好序的有序表,待插入的第i个记录的关键字大于有序表中的最后一个记录的关键字(有序表中关键字最大的记录),需要将其插入有序表;否则,不需要做任何处理。在进行后续处理之前,将r[i]存入哨兵r[0]中,防止后续记录后移的时候将r[i]的值覆盖掉。
将记录插入有序表的过程中,由于并不知道需要将其插入到哪个位置,所以从有序表的最后一个记录r[i-1]开始,依次与r[0](即r[i],r[i]到后面会被覆盖)进行比较,若r[i-1]>r[0],说明需要将r[i]插入到r[i-1]的前面,故将r[i-1]进行后移,依次与有序表中的记录(从后往前)进行比较,并进行后移处理,最终将带插入记录插入到正确的位置。
“依次与有序表中的记录(从后往前)进行比较”,如果从前往后进行记录后移的话,后面的记录将会被覆盖掉。
回顾 “直接插入排序的基本思想:将一个记录插入到已经排好序的有序表中,从而得到一个新的,记录增长1的有序表。”,如何理解这句话呢?在Step1中,{5}为已经排好序的有序表,我们将记录3插入到{5}中,最终得到了一个新的,记录增长1的有序表{3,5},依次进行,最终可以将一个顺序表排成一个有序表。
相关链接:
冒泡排序 https://www.cnblogs.com/yongjin-hou/p/13858510.html
简单选择排序 https://www.cnblogs.com/yongjin-hou/p/13859148.html
希尔排序 https://www.cnblogs.com/yongjin-hou/p/13866344.html
堆排序 https://www.cnblogs.com/yongjin-hou/p/13873770.html
归并排序 https://www.cnblogs.com/yongjin-hou/p/13921147.html
快速排序 https://www.cnblogs.com/yongjin-hou/p/13950379.html
参考书籍:程杰 著,《大话数据结构》,清华大学出版社。