C 實現經典排序演算法(二) 選擇排序和快速排序

2021-10-07 16:24:02 字數 2999 閱讀 2270

俗話說得好:排序千萬種,方便第一種,排序不規範,找bug兩行淚。上次寫了一篇關於插入排序和氣泡排序的博文,這次再來介紹一下選擇排序法和快速排序法。

選擇排序法,顧名思義就是將需要的數選擇出來,再放到需要的地方。例如有乙個陣列[1,5,4,6,7,3,2],對這個陣列進行選擇排序的話,大致可以歸納為以下幾個步驟:

假設第i個元素即為最小的資料,採用temp變數記錄其下標

依次遍歷從i+1開始的後面的元素,並與tempi相比較,若小於temp則記錄當前元素的下標

步驟二遍歷完成之後,將temp下標的元素與步驟一中的元素進行交換,即實現了將最小的資料選擇出來並挪到前面的過程。

重複步驟

一、二、三

採用偽**表示如下:

for

(int i =

0; i < arr.

size()

;++i)

if(temp == i)

)continue

;//如果第i個元素就是最小元素,則進行下一輪迴圈

else

swap

((arr + temp)

,(arr + i));

//將第i個元素和第temp個元素交換位置,進行下一輪迴圈

**實現如下:

#include

/*交換函式,通過指標交換兩個位址的值

@param 待交換值1

@param 帶交換值2

*/template

<

typename t>

void

swap

(t* value1, t* value2)

/*#採用泛型,可傳入任意需要比較的型別

@param 待排序的陣列

@param 待排序陣列的長度

*/template

<

typename t>

void

selectsort

(t arr[

], size_t len)if(

*(arr + temp)==*

(arr + i)

)continue

;else

swap

((arr + temp)

,(arr + i));

}}

輸出結果測試:

那麼問題來了,該演算法的時間複雜度和空間複雜度分別是多少呢?很明顯的是空間複雜度為o(1)。時間複雜度為o(n²)。選擇排序法相比於冒泡和插入排序法,選擇排序的交換次數會有明顯的減少,其最多的交換次數為n - 1次。

不論是氣泡排序,插入排序還是選擇排序,其時間複雜度都是o(n²)。對於消耗的時間來說,並沒有非常明顯的改善。為了解決這一問題,快速排序——qsort應運而生。

快速排序法的基本思想:

先找乙個基準數(一般為待排序陣列的第乙個值),同時設定兩個指標,乙個指向待排陣列的最左元素(第乙個),乙個指向待排陣列最右側(最後乙個元素)

移動右側指標將小於基準數的元素移至左側。此時基準數的位置發生了變化

移動左側指標將大於基準數的元素移至右側。此時基準數的位置也發生了變化

重複步驟2,3直至左側指標和右側指標指向同乙個位置。

這樣一趟結束後,基準點會將所有的元素分為左右兩部分,再分別對左右兩部分重複1,2,3,4步驟即可得到有序陣列。

如下圖所示,先找出乙個基準數(圖中的3),經過第一輪移動後,待排陣列被拆成了兩塊,再分別對左右兩塊作同樣的排序。依此類推,便可以實現快速排序演算法了。

基於上述思路,快速排序法可以採用遞迴法來實現,關鍵則是要找到每一輪迴圈後其基準元素所在的下標,然後將其分為兩段,再進行快速排序。其偽**可描述為:

int

getrefindex

(t arr,

unsigned

int left,

unsigned

int right)

//for迴圈結束後即left == right,因此可以直接將temp放入

arr[right]

= temp;

//arr[left] = temp也行

return left;

//return right也行。

上面的步驟完成後,只需要遞迴呼叫即可了。其偽**如下:

void

myqsort

(t arr,

unsigned

int left,

unsigned

int right)

根據上面的思路,我們可以寫出以下測試**:

#pragma once

#include

using

namespace std;

template

<

typename t>

intgetrefindex

(t arr,

unsigned

int left,

unsigned

int right)

//迴圈結束後,left == right成立

*(arr + left)

= temp;

return left;

}template

<

typename t>

void

myqsort

(t arr,

unsigned

int left,

unsigned

int right)

}

測試結果如下:

快速排序的時間複雜度平均為o(nlgn)相比於其他的o(n²)來的要小,但是這種遞迴方式的空間複雜度將不再是o(1)而是o(nlgn)。這就是典型的以空間換時間的案例。

Python實現經典排序演算法

import random lis list range 100 random.shuffle lis print lis def bubblesort arr for i in range 1 len arr for j in range 0 len arr i if arr j arr j 1 ...

Python 實現經典排序演算法

穩定的排序演算法 氣泡排序 插入排序 歸併排序和基數排序。不是穩定的排序演算法 選擇排序 快速排序 希爾排序 堆排序。a 80,15,45,35,88,46,55,66,22,99,0,1,100 for j in range 0,len a for i in range 0,len a 1 if ...

Python實現經典排序演算法 堆排序

上次說到了經典演算法選擇排序,感覺是比較簡單的演算法,這一次說一說稍微有點難度的堆排序。堆排序的時間複雜度要明顯優於前面的氣泡排序,插入排序和選擇排序 侷限於n較大時 先來講講堆 二叉堆 是乙個陣列,它可以近似被看作是乙個完全二叉樹。樹上每乙個節點對應乙個元素,除了最底層外,該樹是完全充滿的,而且是...