插入排序与循环不变式

  插入排序的做法是在循环遍历整个待排序序列时,每遍历一个元素,就会将此元素插入到一个已排好序的列表中,待整个序列遍历完毕,则已排好序的列表就是排序的结果,另外已排好序的列表并不需要额外的存储空间,也就是可以进行原址排序。
具体做法如下:
  有一序列长度为8
4
6
1
3
9
5
8
2

  从第一个元素i = 0开始遍历,取到4,而已排序列表(设为A)此时为空,直接将此元素插入A中即可,黄色的代表已排好序的列表,i++;

4
6
1
3
9
5
8
2

  继续遍历i = 1,此时元素为6,往已排序列表中插入,结果如下,i++

4
6
1
3
9
5
8
2

  继续遍历i = 2,此时元素为1,往已排序列表中插入,此时要注意,要将1插入到A中,要将比1大的元素一个个依次往后挪,结果如下,i++

1
4
6
3
9
5
8
2

  按以上流程依次进行,直接将所有元素遍历,得到的结果就是已排好序的结果了

1
2
3
4
5
6
8
9

 

  

 1 void InsertSort(int num[], int nSize){  
 2         for(int i = 0;i < nSize;++i){  
 3             int j = i - 1;  
 4             int tobeInsert = num[i];  
 5   
 6             //以下是在已排好序的列表中,查找可以插入的位置  
 7             while(j >= 0 && num[j] > tobeInsert){  
 8                 //执行到此处的都表示,比待插入元素要大,要将此元素往后挪  
 9                 num[j + 1] = num[j];  
10                 j = j - 1;  
11             }  
12             //while循环结束后,要么是j = -1,表示没有找到任何元素比待插入的元素小,要么是找到了一个元素比待插入元素小的位置  
13             //如果是j = -1,则说明待插入元素是已排好序中最小的了,则直接插入到0位置即可  
14             //如果是第二种情况,则将待插入元素插入到找到的元素的后面  
15             //结合上面两种情况,用以下代码就能概括了  
16             num[j + 1] = tobeInsert;  
17         }  
18     }  
  其实以上代码,i从1直接开始就行了,因为i=0时,已排序的列表为空,不需要查找位置的过程。
  插入排序的时间复杂度为O(N 2)
 
  按算法导论第二章的定义,A按序排序的性质,称为循环不变式,循环不变式是用来帮助我们理解算法的正确性的,关于循环不变式,需要证明以下三条性质
是对的。
      初始化:循环的第一次迭代之前,它为真
      保持:如果循环的某次迭代之前它为真,那么下次迭代之前它仍为真
      终止:在循环终止时,不变式为我们提供一个有用的性质,该性质有助于证明算法是正确的。
 
      对以上算法,当i = 0时,A为空,当i = 1时,A只有一个元素,循环不变式都是成立的。所以初始化是正确的。
      保持:其后每一次迭代,新的元素插入时,都将A中的元素比新插入元素大的元素往后挪,保持了A的按序排列
      终止:当i = nSize - 1时,A中的元素个数为nSize - 1,此都已经按序排序,此时将i指向的元素插入A中,A的元素为nSize
      当i = nSize,循环中止,A的元素个数和nSize,且都已按序排列,这就是我们想要的排序结果,说明算法正确 .

转载于:https://www.cnblogs.com/zengyg/p/8732967.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值