演算法學習(二)快速排序(下)

2021-08-27 16:49:28 字數 1622 閱讀 6660

快速排序採取的是分治法,所以怎麼把乙個無序的陣列以某個點為中界來將其拆分成有序的兩部分,這是其快 排的核心方法。

在上一章中,是一開始提出來的「快速排序」,但是這個世界上在某些地方總會有些牛人,一點一點地去優化,提出更有意思,更簡單的方法。

看下圖,這是快排另乙個經典的拆分方法:

1)這裡是將陣列的最後乙個元素作為基準數來比較,如圖中a[8] = 10。

2)同樣的,也有兩個指標i 跟 j,但 i 一開始的位置是起始位置 - 1,如上面應該是 0 - 1 = -1。為什麼會是這樣呢?

3)j 會一直向右掃,每次掃都會比較當前數a[j] 是否比基準數小,如果是的話,則會把 i + 1位置的數跟a[j]的值互調。這裡我們就要回答一下為什麼是要拿 i + 1位置的數跟 j 相調,為什麼一開始要i 設定成 low - 1呢,就是因為 i 當前位置的值a[i] 其實就是上一輪交換的數,它本來就是比基數小的數了,是不需要改變的,而下乙個數如果沒有被交換過,那麼它一定是比基準數要的,所以被交換到後面是很正確的,從這一點也可以看出這個拆分法的巧妙之處了。

4)從上面幾個步驟可以看出,剛一開始,當j = 0的時候,a[j] = 9是比10小的,所以 i++之後就變成0了,雖然要做交換操作,但其實是不變的。然後 i 的位置就變成0了,而 j 繼續往前,發現7,於是 i 要前進一步(當前i是上輪交換的),然後交換,然後 j 再繼續,一直到最後乙個元素。

5)最後再讓 i 前進一點,然後拿a[i]的值跟key互換,這樣第一輪的交換就結束了,而此時陣列是變成以10為界的兩個小陣列,如上圖最後一行。

根據這樣的邏輯,**如下:

public static int partition2(int a, int low, int high)

} helper.swap(a, ++i, high);

return i;

}

現在我們利用這個新的拆分函式來遞迴:

public static void quicksort2(int a, int low, int high)

}

最後當然,也要來驗證一下其正確性,是吧

before:		11 9 12 7 4 57 44 23 10 

round 1: 9 7 4 10 12 57 44 23 11

round 2: 4 7 9 10 12 57 44 23 11

round 3: 4 7 9 10 12 57 44 23 11

round 4: 4 7 9 10 11 57 44 23 12

round 5: 4 7 9 10 11 12 44 23 57

round 6: 4 7 9 10 11 12 44 23 57

round 7: 4 7 9 10 11 12 23 44 57

after: 4 7 9 10 11 12 23 44 57

同樣的,我們可以看到round 1展示的就是我們上圖中所展示的最後一行。

有興趣的童鞋可以看一下上一章演算法學習(二)快速排序(上)

演算法學習 快速排序

快速排序 分治演算法 const int n 1e6 10 int a n a 待排序陣列,l 排序陣列的起始下標,r 排序陣列的結束下標 void quick sort int a,int l,int r 遞迴的終止條件 int x a l 選取排序的比較物件 int i l 1 設定排序的左指標...

演算法學習 快速排序

1 基本思想 取待排序陣列第乙個數作為參照數,建立left和right陣列,left儲存小於參照數的陣列集合,right儲存大於參照數的陣列集合,然後分別對left和right進行遞迴呼叫排序。2 舉例 11,2,3,43,23,5,6,9,10 取任意的乙個數為基準數 temp arr 0 遍歷陣...

排序演算法學習 快速排序

快速排序 作為氣泡排序的一種改進 通過設定乙個標誌值 通常為陣列第乙個元素pivot 一次快排將陣列分成兩個部分,一部分 公升序 前一部分 小於標誌值pivot,另一部分大於標誌值 公升序 後面部分 各部分內部可以是 通常也是 無序的。通過遞迴地呼叫這樣的排序,使得最終陣列所有的元素有序。一次具體的...