几种排序算法

来源:互联网 发布:electron linux 编辑:程序博客网 时间:2024/05/01 11:15

冒泡排序

冒泡排序(BubbleSort)的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。重复以上过程,仍从第一对数开始比较(因为可能由于第2个数和第3个数的交换,使得第1个数不再小于第2个数),将小数放前,大数放后,一直比较到最大数前的一对相邻数,将小数放前,大数放后,第二趟结束,在倒数第二个数中得到一个新的最大数。如此下去,直至最终完成排序。
 

 

  由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。
 

 

  用二重循环实现,外循环变量设为i,内循环变量设为j。外循环重复9次,内循环依次重复9,8,...,1次。每次进行比较的两个元素都是与内循环j有关的,它们可以分别用a[j]和a[j+1]标识,i的值依次为1,2,...,9,对于每一个i, j的值依次为1,2,...10-i。
 

 

  冒泡排序是稳定的。

产生

   在许多程序设计中,我们需要将一个数列进行排序,以方便统计,常见的排序方法有冒泡排序,二叉树排序,选择排序等等。而冒泡排序一直由于其简洁的思想方法和比较高的效率而倍受青睐。

排序过程

   设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。

算法示例

   49 13 13 13 13 13 13 13
 

 

  38 49 27 27 27 27 27 27
 

 

  65 38 49 38 38 38 38 38
 

 

  97 65 38 49 49 49 49 49
 

 

  76 97 65 49 49 49 49 49
 

 

  13 76 97 65 65 65 65 65
 

 

  27 27 76 97 76 76 76 76
 

 

  49 49 49 76 97 97 97 97
 

 

  Procedure BubbleSort(Var R : FileType) //从下往上扫描的起泡排序//
 

 

  Begin
 

 

  For I := 1 To N-1 Do //做N-1趟排序//
 

 

  begin
 

 

  NoSwap := True; //置未排序的标志//
 

 

  For J := N - 1 DownTo 1 Do //从底部往上扫描//
 

 

  begin
 

 

  If R[J+1]< R[J] Then //交换元素//
 

 

  begin
 

 

  Temp := R[J+1]; R[J+1 := R[J]; R[J] := Temp;
 

 

  NoSwap := False
 

 

  end;
 

 

  end;
 

 

  If NoSwap Then Return//本趟排序中未发生交换,则终止算法//
 

 

  end
 

 

  End; //BubbleSort//
 

 

  该算法的时间复杂性为O(n^2),算法为稳定的排序方法。

 

快速排序

算法过程  设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。一趟快速排序的算法是:
 

 

  1)设置两个变量I、J,排序开始的时候:I=0,J=N-1;
 

 

  2)以第一个数组元素作为关键数据,赋值给key,即 key=A[0];
 

 

  3)从J开始向前搜索,即由后开始向前搜索(J=J-1),找到第一个小于key的值a[j],并与key交换;
 

 

  4)从I开始向后搜索,即由前开始向后搜索(I=I+1),找到第一个大于key的a[i],与key交换;
 

 

  5)重复第3、4、5步,直到 I=J; (3,4步是在程序中没找到时候j=j-1,i=i+1。找到并交换的时候i, j指针位置不变。另外当i=j这过程一定正好是i+或j+完成的最后另循环结束)
 

 

  例如:待排序的数组A的值分别是:(初始关键数据:X=49) 注意关键X永远不变.永远是和X进行比较 无论在什么位子 最后的目的就是把X放在中间小的放前面大的放后面

 

 

  A[0] 、 A[1]、 A[2]、 A[3]、 A[4]、 A[5]、 A[6]:

 

  49 38 65 97 76 13 27

 

  进行第一次交换后: 27 38 65 97 76 13 49

 

  ( 按照算法的第三步从后面开始找)

 

  进行第二次交换后: 27 38 49 97 76 13 65

 

  ( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时:I=3 )

 

  进行第三次交换后: 27 38 13 97 76 49 65

 

  ( 按照算法的第五步将又一次执行算法的第三步从后开始找

 

  进行第四次交换后: 27 38 13 49 76 97 65

 

  ( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时:J=4 )

 

  此时再执行第三步的时候就发现I=J,从而结束一趟快速排序,那么经过一趟快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。

 

  快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如下所示:

 

  初始状态 {49 38 65 97 76 13 27}

 

    进行一次快速排序之后划分为 {27 38 13} 49 {76 97 65}

 

  分别对前后两部分进行快速排序 {27 38 13} 经第三步和第四步交换后变成 {13 27 38} 完成排序。

 

  {76 97 65} 经第三步和第四步交换后变成 {65 76 97} 完成排序。

  直接插入排序

直接插入排序(straight insertion sort)的作法是:
 

 

  每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
 

 

  第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
 

 

  直接插入排序属于稳定的排序,时间复杂性为o(n^2),空间复杂度为O(1)。
 

 

  直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
 

 

  值得注意的是,我们必需用一个存储空间来保存当前待比较的数值,因为当一趟比较完成时,我们要将待比较数值置入比它小的数值的后一位 插入排序类似玩牌时整理手中纸牌的过程。插入排序的基本方法是:每步将一个待排序的记录按其关键字的大小插到前面已经排序的序列中的适当位置,直到全部记录插入完毕为止。

  初始序列:

 

  i=1 [46] 58 15 45 90 18 10 62

 

  ↓

 

  i=2 [46 58] 15 45 90 18 10 62

 

  ┌——┘

 

  ↓

 

  i=3 [15 46 58] 45 90 18 10 62

 

  ┌——┘

 

  ↓

 

  i=4 [15 45 46 58] 90 18 10 62

 

  ↓

 

  i=5 [15 45 46 58 90] 18 10 62

 

  ┌—————┘

 

  ↓

 

  i=6 [15 18 45 46 58 90] 10 62

 

  ┌————————┘

 

  ↓

 

  i=7 [10 15 18 45 46 58 90] 62

 

  ┌—┘

 

  ↓

 

  i=8 [10 15 18 45 46 58 62 90]

注:本文为作者从百度百科选取整理

原创粉丝点击