一步步學資料結構與演算法 12 排序 下

2021-09-25 12:47:12 字數 2098 閱讀 4829

1.演算法原理

快排的思想是這樣的:如果要排序陣列中下標從p到r之間的一組資料,我們選擇p到r之間的任意乙個資料作為pivot(分割槽點)。然後遍歷p到r之間的資料,將小於pivot的放到左邊,將大於pivot的放到右邊,將povit放到中間。經過這一步之後,陣列p到r之間的資料就分成了3部分,前面p到q-1之間都是小於povit的,中間是povit,後面的q+1到r之間是大於povit的。根據分治、遞迴的處理思想,我們可以用遞迴排序下標從p到q-1之間的資料和下標從q+1到r之間的資料,直到區間縮小為1,就說明所有的資料都有序了。

遞推公式:quick_sort(p…r) = quick_sort(p…q-1) + quick_sort(q+1, r)

終止條件:p >= r

2.**實現

private static void quicksort(int a, int head, int tail)

a[low] = pivot;

if(low>head+1) quicksort(a,head,low-1);

if(high3.效能分析

1)演算法穩定性:

因為分割槽過程中涉及交換操作,如果陣列中有兩個8,其中乙個是pivot,經過分割槽處理後,後面的8就有可能放到了另乙個8的前面,先後順序就顛倒了,所以快速排序是不穩定的排序演算法。比如陣列[1,2,3,9,8,11,8],取後面的8作為pivot,那麼分割槽後就會將後面的8與9進行交換。

2)時間複雜度:最好、最壞、平均情況

快排也是用遞迴實現的,所以時間複雜度也可以用遞推公式表示。

如果每次分割槽操作都能正好把陣列分成大小接近相等的兩個小區間,那快排的時間複雜度遞推求解公式跟歸併的相同。

t(1) = c; n=1 時,只需要常量級的執行時間,所以表示為 c。

t(n) = 2*t(n/2) + n; n>1

所以,快排的時間複雜度也是o(nlogn)。

如果陣列中的元素原來已經有序了,比如1,3,5,6,8,若每次選擇最後乙個元素作為pivot,那每次分割槽得到的兩個區間都是不均等的,需要進行大約n次的分割槽,才能完成整個快排過程,而每次分割槽我們平均要掃瞄大約n/2個元素,這種情況下,快排的時間複雜度就是o(n^2)。

前面兩種情況,乙個是分割槽及其均衡,乙個是分割槽極不均衡,它們分別對應了快排的最好情況時間複雜度和最壞情況時間複雜度。那快排的平均時間複雜度是多少呢?t(n)大部分情況下是o(nlogn),只有在極端情況下才是退化到o(n^2),而且我們也有很多方法將這個概率降低。

3)空間複雜度:快排是一種原地排序演算法,空間複雜度是o(1)

歸併和快排用的都是分治思想,遞推公式和遞迴**也非常相似,那它們的區別在**呢?

1.歸併排序,是先遞迴呼叫,再進行合併,合併的時候進行資料的交換。所以它是自下而上的排序方式。何為自下而上?就是先解決子問題,再解決父問題。

2.快速排序,是先分割槽,在遞迴呼叫,分割槽的時候進行資料的交換。所以它是自上而下的排序方式。何為自上而下?就是先解決父問題,再解決子問題。

1.o(n)時間複雜度內求無序陣列中第k大元素,比如4,2,5,12,3這樣一組資料,第3大元素是4。

我們選擇陣列區間a[0…n-1]的最後乙個元素作為pivot,對陣列a[0…n-1]進行原地分割槽,這樣陣列就分成了3部分,a[0…p-1]、a[p]、a[p+1…n-1]。

如果如果p+1=k,那a[p]就是要求解的元素;如果k>p+1,說明第k大元素出現在a[p+1…n-1]區間,我們按照上面的思路遞迴地在a[p+1…n-1]這個區間查詢。同理,如果k時間複雜度分析?

第一次分割槽查詢,我們需要對大小為n的陣列進行分割槽操作,需要遍歷n個元素。第二次分割槽查詢,我們需要對大小為n/2的陣列執行分割槽操作,需要遍歷n/2個元素。依次類推,分割槽遍歷元素的個數分別為n、n/2、n/4、n/8、n/16…直到區間縮小為1。如果把每次分割槽遍歷的元素個數累加起來,就是等比數列求和,結果為2n-1。所以,上述解決問題的思路為o(n)。

2.有10個訪問日誌檔案,每個日誌檔案大小約為300mb,每個檔案裡的日誌都是按照時間戳從小到大排序的。現在需要將這10個較小的日誌檔案合併為1個日誌檔案,合併之後的日誌仍然按照時間戳從小到大排列。如果處理上述任務的機器記憶體只有1gb,你有什麼好的解決思路能快速地將這10個日誌檔案合併?

一步步學資料結構與演算法 10 遞迴

1.遞迴是一種非常高效 簡潔的編碼技巧,一種應用非常廣泛的演算法,比如dfs深度優先搜尋 前中後序二叉樹遍歷等都是使用遞迴。2.方法或函式呼叫自身的方式稱為遞迴呼叫,呼叫稱為遞,返回稱為歸。3.基本上,所有的遞迴問題都可以用遞推公式來表示,比如 f n f n 1 1 f n f n 1 f n 2...

一步步學資料結構與演算法 20 雜湊演算法 上

帶著問題來學習 1.如何防止資料庫中的使用者資訊被脫庫?2.你會如何儲存使用者密碼這麼重要的資料嗎?僅僅 md5 加密一下儲存就夠了嗎?3.在實際開發中,我們應該如何用雜湊演算法解決問題?1.定義 將任意長度的二進位制值串對映成固定長度的二進位制值串,這個對映的規則就是雜湊演算法,而通過原始資料對映...

一步步學資料結構與演算法 09 佇列

1.先進者先出,這就是典型的 佇列 結構。2.支援兩個操作 入隊enqueue 放乙個資料到隊尾 出隊dequeue 從隊頭取乙個元素。3.所以,和棧一樣,佇列也是一種操作受限的線性表。1.佇列api public inte ce queue2.陣列實現 順序佇列 public class arra...