資料結構 - 快速排序舉例
之前學習的時候就一直很注意快速排序,但是看完總是忘記,這一次看到一個視訊系列講解十分透徹,可以分享給大家
https://www.bilibili.com/video/av17888877這是一個三集的講解快速排序的,給予充足的思考時間,方便大家學習,再次感謝B站博主的分享.
快速排序使用分而治之來獲得與歸併排序相同的優點,而不使用額外的儲存。然而,作為權衡,有可能列表不能被分成兩半。當這種情況發生時,我們將看到效能降低。
快速排序首先選擇一個值,該值稱為 樞軸值
。雖然有很多不同的方法來選擇樞軸值,我們將使用列表中的第一項。樞軸值的作用是幫助拆分列表。樞軸值屬於最終排序列表(通常稱為拆分點)的實際位置,將用於將列表劃分為快速排序的後續呼叫。
Figure 12 展示 54 將作為我們的第一個樞紐值。由於我們已經看過這個例子幾次,我們知道 54 最終將會在當前持有 31 的位置。接下來將發生分割槽過程。它將找到拆分點,同時將其他項移動到列表的適當側,小於或大於樞軸值。
Figure 12
分割槽從通過在列表中剩餘專案的開始和結束處定位兩個位置標記(我們稱為左標記和右標記)開始(Figure 13中的位置 1 和 8 )。分割槽的目標是移動相對於樞軸值位於錯誤側的項,同時也收斂於分裂點。 Figure13展示了我們定位54的位置的過程。
Figure 13
我們首先增加左標記,直到我們找到一個大於樞軸值的值。 然後我們遞減右標,直到我們找到小於樞軸值的值。我們發現了兩個相對於最終分裂點位置不適當的項。 對於我們的例子,這發生在 93 和 20。現在我們可以交換這兩個專案,然後重複該過程。
在右標變得小於左標記的點,我們停止。右標記的位置現在是分割點。樞軸值可以與拆分點的內容交換,樞軸值現在就位(Figure 14)。 此外,分割點左側的所有項都小於樞軸值,分割點右側的所有項都大於樞軸值。現在可以在分割點處劃分列表,並且可以在兩半上遞迴呼叫快速排序。
目前.看到的都是比較長的實現,我再次簡單分析一下.
目標: 對一組資料進行排序 方法:快速排序 分析:一般來說選擇列表的第一個元素進行作為midvalue,該變數將作為一個隔板,將原有列表中的資料分成 兩個部分,一個部分為小於midvalue的,另外一個部分顯然就是大於midvalue的.將列表中的資料分成兩部 分後,那麼此時midvalue的位置實際上就是最後排序完成後midvalue的位置.之後再對原有列表小於 midvalue和大於midvalue部分充分上述分割操作,即遞迴. 注意: 1. 遞迴的條件,因為我們對列表分割的最終是將其分為一個一個的,之後也就不能再進行切分了,因此這作為遞迴的條件之一 2. 注意原始碼中出現first和last,是因為我們所有的操作都是針對原來列表的,每一次切分都會造成列表的縮短,索引會出現問題.
原始碼呈上:
def quicksort(nums, first, last):
# 遞迴判斷條件
if first >= last:
return
# 獲取midvalue值,將原列表資料進行切分
midvalue = nums[first]
left = first
right = last
while left < right:
while left <= right and nums[right] >= midvalue:
right -= 1
nums[left] = nums[right]
while left <= right and nums[left] < midvalue:
left += 1
nums[right] = nums[left]
nums[left] = midvalue
# 遞迴
quicksort(nums, first, left -1)
quicksort(nums, left+1, last)
nums= [1,54,575,5675,75]
quicksort(nums, 0, len(nums)-1)
print nums
結果:
/usr/bin/python2.7 "/home/trami/Data Structure/study.py"
[1, 54, 75, 575, 5675]
Process finished with exit code 0