五类插入排序

插入排序可分为五类:

1.  直接插入排序算法
基本操作:将一个记录插入到已排好序的有序表中,从而得到一个新的、记录增1的有序表。
时间复杂度:O(n^2)
代码:java表示

 

 

分析:

    直接插入排序的好处就是算简单明了,程序容易实现.但是效率就不可避免的比较低下.程序除了需要一个记录数据的数组以外还要有一个临时的辅助空间.

    从程序中可以看出,即使假设数组已经是顺序的,程序仍旧需要进行n - 1次的比较,但是不用进行数组元素的移动.当数组是逆序的时候,程序需要进行(n + 2)(n - 1) / 2次的比较,另加(n + 4)(n - 1) / 2次的数组元素移动.综上平均计算一下的话,差不多要进行(n ^ 2) / 4次的比较和移动,所以复杂度应该是O(n ^ 2).

 

2.  折半插入排序算法
基本操作:由于直接插入排序的基本操作是在一个有序表中进行查找的和插入的,所以这个“查找”操作可以利用“折半查找”来实现,这样可以减少查找的时间复杂度。
时间复杂度:O(n^2)
代码:java表示

 

 

分析:这个方法可以减少数据比较的次数,但是数据移动还是要一步一步的进行(仍旧需要移动大约i / 2个已排好序的元素),所以时间复杂度没有什么实质的改善.治标不治本的方法.

3.  2-路插入排序算法
上面的二分插入减少的是数据比较的次数,而二路插入的方法可以减少数据移动的次数.

 

 

 

这个二路插入的算法可以比二分插入算法节约一半的运行时间,但是程序比较复杂.
    上面的程序另外使用了一个大小为n的辅助空间,并且把b看成了循环向量.low是数组中最小的元素,high是数组中最大的元素,如果待排序的元素小于low则放在first的前面,如果比high小则放在high的后面.

    在<<计算机程序设计艺术>>中作者说到过一种方法,把输入区域当作一个循环表,而且位置N同1相邻.根据上一次插入的元素是落在已排序元素的中心的左面还是右面,而从当前未排序元素段的右面或是左面来取新的元素.过后通常需要"转动"这个区域.通过这个方法可以仅用N + 1的空间同时进行输入,输出和排序.

4.  表插入排序算法
基本操作:和直接插入排序相比,不同之处仅是以修改2n次指针代替了移动记录,排序过程中所需进行的关键字间比较次数相同。
时间复杂度:O(n^2)
代码:略
5.  希尔排序(缩小增量排序)算法
      基本思想:
  不断把待排序的对象分成若干个小组,对同一小组内的对象采用直接插入法排序,当完成了所有对象都分在一个组内的排序后,排序过程结束。每次比较指定间距的两个数据项,若左边的值小于右边的值,则交换它们的位置。间距d按给定公式减少: di+1 =(di +1)/2 ,直到d等于1为止。D可以选取{9,5,3,2,1}。
算法步骤:
  Step1 将n个元素个数列分为5个小组,在每个小组内按直接插入法排序;
  step2 在第i步,分组个数取 di+1 =(di +1)/2 {9,5,3,2,1};相临两组之间的对应元素进行比较,如果ai>aj,则交换它们的位置;
  Step3 当dK = 1的循环过程完成后,排序过程结束。
基本操作:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
希尔排序的一个特点是:子序列的构成不是简单地“逐段分割”,而是将相隔某个“增量” 的记录组成一个子序列。希尔排序的分析是一个复杂的问题,因为它的时间是所取“增量”序列的函数,这涉及一些数学上尚未解决的难题。因此,到目前为止尚未有人求得最好的增量序列。增量序列可以有各种方法,但需要注意:应使增量序列中的值没有除1之外的公因子;并且最后一个增量值必须等于1。
c 代码:

 

分析:Shell排序的时间复杂度不是O(n ^ 2),而是根据所选的增量序列而定的.

 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lixiang040330624/archive/2009/10/09/4647512.aspx

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章