排序演算法比較

2021-09-24 23:35:45 字數 4385 閱讀 2555

比較排序和非比較排序

​ 常見的排序演算法都是比較排序,非比較排序包括計數排序、桶排序和基數排序,非比較排序對資料有要求,因為資料本身包含了定位特徵,所有才能不通過比較來確定元素的位置。

​ 比較排序的時間複雜度通常為o(n2)或者o(nlogn),比較排序的時間複雜度下界就是o(nlogn),而非比較排序的時間複雜度可以達到o(n),但是都需要額外的空間開銷。

​ 比較排序時間複雜度為o(nlogn)的證明:

​ a1,a2,a3……an序列的所有排序有n!種,所以滿足要求的排序a1』,a2』,a3』……an』(其中a1』<=a2』<=a3』……<=an』)的概率為1/n!。基於輸入元素的比較排序,每一次比較的返回不是0就是1,這恰好可以作為決策樹的乙個決策將乙個事件分成兩個分支。比如氣泡排序時通過比較a1和a2兩個數的大小可以把序列分成a1,a2……an與a2,a1……an(氣泡a2上公升乙個身位)兩種不同的結果,因此比較排序也可以構造決策樹。根節點代表原始序列a1,a2,a3……an,所有葉子節點都是這個序列的重排(共有n!個,其中有乙個就是我們排序的結果a1』,a2』,a3』……an』)。如果每次比較的結果都是等概率的話(恰好劃分為概率空間相等的兩個事件),那麼二叉樹就是高度平衡的,深度至少是log(n!)。

​ 又因為

n! < nn ,兩邊取對數就得到log(n!)n!=n(n-1)(n-2)(n-3)…1 > (n/2)^(n/2) 兩邊取對數得到 log(n!) > (n/2)log(n/2) = ω(nlogn),所以 log(n!) = ω(nlogn)。

​ 因此log(n!)的增長速度與 nlogn 相同,即 log(n!)=θ(nlogn),這就是通用排序演算法的最低時間複雜度o(nlogn)的依據。

穩定排序和非穩定排序

簡單地說就是所有相等的數經過某種排序方法後,仍能保持它們在排序之前的相對次序,我們就

說這種排序方法是穩定的。反之,就是非穩定的。

比如:一組數排序前是a1,a2,a3,a4,a5,其中a2=a4,經過某種排序後為a1,a2,a4,a3,a5,

則我們說這種排序是穩定的,因為a2排序前在a4的前面,排序後它還是在a4的前面。假如變成a1,a4,

a2,a3,a5就不是穩定的了。

內排序和外排序

在排序過程中,所有需要排序的數都在記憶體,並在記憶體中調整它們的儲存順序,稱為內排序;

在排序過程中,只有部分數被調入記憶體,並借助記憶體調整數在外存中的存放順序排序方法稱為外排序。

平均情況

最好情況

最壞情況

歸併排序

o(nlogn)

o(nlogn)

o(nlogn)

基數排序

o(n)

o(n)

o(n)

快速排序

o(nlogn)

o(nlogn)

o(n2)

希爾排序

o(n1.5)

o(n)

o(n1.5)

插入排序

o(n2)

o(n)

o(n2)

選擇排序

o(n2)

o(n2)

o(n2)

排序的穩定性和複雜度

不穩定:

穩定:

**參考

#_*_coding:utf-8_*_

import random

#選擇排序遞迴實現

defsel_sort_rec

(list

,n):

if n ==0:

return

max_j = n

for j in

range

(n):

iflist

[j]>

list

[max_j]

: max_j = j

list

[n],

list

[max_j]

=list

[max_j]

,list

[n] sel_sort_rec(

list

,n-1

)#選擇排序迴圈實現

defsel_sort

(list):

for i in

range

(len

(list))

: min_j = i

for j in

range

(i+1

,len

(list))

:iflist

[min_j]

>

list

[j]:

min_j = j

list

[min_j]

,list

[j]=

list

[min_j]

,list

[j]#插入排序遞迴實現

defins_sort_rec

(list

,n):

if n ==0:

return

ins_sort_rec(

list

,n-1

) j = n

while j >

0and

list

[j-1

]>

list

[j]:

list

[j-1],

list

[j]=

list

[j],

list

[j-1

] j -=

1#插入排序迴圈實現

defins_sort

(list):

for i in

range(1

,len

(list))

: j = i

while j >

0and

list

[j-1

]>

list

[j]:

list

[j-1],

list

[j]=

list

[j],

list

[j-1

] j -=

1#遞迴的合併排序實現

defmerge_sort

(a):

iflen

(a)<=1:

return a

middle =

len(a)//2

lefta = a[

:middle]

righta = a[middle:

] lefta_sorted = merge_sort(lefta)

righta_sorted = merge_sort(righta)

return merge(lefta_sorted,righta_sorted)

#合併兩個已經排序的序列

defmerge

(left, right)

: i, j =0,

0 alist =

while i <

len(left)

and j <

len(right)

:if left[i]

< right[j]:)

i +=

1else:)

j +=

1while i <

len(left)

:#左邊剩餘資料處理

) i +=

1while j <

len(right)

:#右邊剩餘資料處理

) j +=

1return alist

defmain()

:list

=[random.randint(1,

10)for x in

range(10

)]sel_sort_rec(

list,9

)print

("選擇排序遞迴實現:"

+str

(list))

sel_sort(

list

)print

("選擇排序迴圈實現:"

+str

(list))

merge_sort(

list

)print

("合併排序實現結果:"

+str

(list))

if __name__ ==

'__main__'

: main(

)

參考鏈結

排序演算法比較

本章中已經研究並仔細分析了多個內部排序方法。對於這些內部排序方法之間的比較,主要從以下幾個方面綜合考慮 時間複雜度 空間複雜度 演算法穩定性 演算法簡單性 待排序記錄數 n的大小 記錄本身的資訊量等。選擇n 個整數組成一些隨機排序,各種內部排序方法的實際時間如圖 7 10 所示。從時間複雜度看,所有...

排序演算法比較

排序方法 最好時間 平均時間 最壞時間 輔助儲存 穩定性備註 簡單選擇排序 o n2 o n2 o n2 o 1 不穩定n小時較好 直接插入排序 o n o n2 o n2 o 1 穩定大部分已有序時較好 氣泡排序 o n o n2 o n2 o 1 穩定n小時較好 希爾排序 o n o nlogn...

比較排序演算法

常用的比較排序演算法有 直接插入排序,希爾排序,選擇排序,堆排序,氣泡排序,快速排序,歸併排序等。它們的時間複雜度及空間複雜度為 實現 如下 includeusing namespace std include include 插入排序 void insertsort int a,size t si...