C语言实例解析精粹学习笔记——42(插入排序)
实例说明:
将一个整数数组按从小到大的顺序进行排序。(主要学习基本的插入排序和改进的冒泡排序的算法和应用)
思路1:
从第一个数据开始,分别比较其后的数据,若比它小,则将这两个数的位置交换;从第一个数据开始,直到最后。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAX 100 4 5 6 7 int main() 8 { 9 int TotNumEle; 10 int R[MAX]; 11 int temp; 12 13 printf("Please input the number you will input:"); 14 scanf("%d", &TotNumEle); 15 16 17 if(TotNumEle > MAX) 18 { 19 printf("Sorry, there are too many elements"); 20 return 0; 21 } 22 23 printf("Please input the elements one by one:"); 24 printf("\n"); 25 for(int i=0; i < TotNumEle; i++) 26 { 27 scanf("%d", &R[i]); 28 } 29 30 for(int i=0; i<TotNumEle-1; i++) 31 { 32 for(int j=i+1; j<TotNumEle; j++) //要注意起始标号,刚开始的时候我就搞错了 33 { 34 if(R[i] > R[j]) 35 { 36 temp = R[i]; 37 R[i] = R[j]; 38 R[j] = temp; 39 } 40 } 41 } 42 43 printf("The sequence after sort is :\n"); 44 for(int i=0; i<TotNumEle; i++) 45 { 46 printf("%4d", R[i]); 47 } 48 49 printf("\n"); 50 return 0; 51 }
下面是原书中给出的示例:
采用直接插入排序
1. 基本思路:假设待排序的记录存放在数组R[1..n]中(R[0]不存储待排序的原始数据)。初始时,R[1]自成一个有序区,无须区为R[2..n]。从i=2起直至i=n为止,依次将R[i]插入当前的有序区R[i..i-1]中,生成含n个记录的有序区。
插入排序与打扑克时整理手上的纸牌类似,第一张牌不需要整理,之后的逐张排序。
1 int R[MAX]; 2 3 void Insert_Sort(int n) 4 { 5 int i,j; 6 for(i=2; i<=n; i++) 7 { 8 if(R[i] < R[i-1]) 9 { 10 R[0] = R[i]; j = i-1; //R[0]有点temp的感觉 11 do{ 12 R[j+1] = R[j]; 13 j--; 14 }while(R[0] < R[j]); 15 R[j+1] = R[0]; 16 } 17 } 18 }
以上为关键代码
归纳注释(原书内容):
哨兵的作用:算法中引进的附加记录R[0]称监视哨或哨兵(Sentinel)。哨兵有两个作用:
1)进行查找(插入位置)循环之前,它保存了R[i]的副本,使不致于因记录后移而丢失R[i]的内容;
2)它的主要作用是在循环中“监视”下标变量j是否越界。一旦越界(即j=0),因为R[0]和自己比较,循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界。