上篇博客我們主要聊了比較高效的歸並排序算法,本篇博客我們就來介紹另一種高效的排序算法:快速排序。快速排序的思想與歸並排序類似,都是采用分而治之的方式進行排序的。快速排序的思想主要是取出無序序列中第一個值,然后通過比較將比該值小的元素放到該值的前方,將比該值大的元素放在該值的后方。這樣一來該值前方的數據都要比該值小,該值后方的數據都要比該值大。然后再次對前半部分和后邊半部分無序的數列進行上述操作,這樣不斷的操作,無序的序列的規模不斷被縮小。等問題的規模被縮小到一定程度后,我們的序列就變的有序了。
之前我們說過,當一個問題可以被分成一些相同的子問題時,我們就可以使用遞歸來操作。所以在快速排序的過程中,我們是通過遞歸的方式將問題規模逐漸減小,知道序列為序為止。本篇博客將會給出這一過程,根據示意圖,給出相應的代碼實現。
一、將無序數組進行拆分
在本篇博客,我們先聊一聊如果將大的問題拆分成一些相同的子問題。我們需要對需要排序的數組進行拆分,從無序序列中取出一個值,然后通過比較,將比該值大的放在該值的后方,比該值小的,放在該值的前方。本部分,我們將給出相應的示意圖以及代碼實現。
1.拆分示意圖
下方就是我們上述過程的示意圖。也是快速排序第一輪排序的過程。首先將無序數組中的第一個值進行暫存(temp = 62),經過下述步驟,我們會將那些比62小的元素放到62的前面,比62大的元素放到后邊。low負責遍歷前半部分,將前半部分大於62的值放到后邊,而high負責遍歷后半部分,將后半部分小於62的值放前邊。具體步驟如下所示。
2.代碼實現
根據上述示意圖,我們可以給出相應的代碼實現。如果上述的示意圖理解了,看下方代碼的實現是比較簡單的。partition()函數就負責將一個無序的數組轉變的以第一個值為准,較小的值放在該值的前邊,較大的放在該值的后邊。如下所示。
二、快速排序
實現完拆分方法后,我們就該實現快速排序的代碼了。上面的代碼是快排的核心,接下來做的事情是調用上述的函數將無序數組進行拆分,然后再調用上述函數將前后無序的小數組進行拆分,依次執行下去,我們的數組就是有序的了。其實就是一個遞歸的過程。下方的quickSort()就是這個過程。首先將無需數組調用partition()方法進行拆分,然后再次調用quickSort()方法執行前半部分,同樣的調用quickSort()方法執行后半部分。代碼如下所示。
定義完快速排序的核心方法后,接下來就是使用了。下方的QuickSort就是相應的快速排序類,QuickSort還是要遵循SortType這個排序協議的,而sort()方法則是該協議中定義的對外調用的接口。具體代碼如下所示。
三、測試用例
用我QuickSort類遵循了SortType方法,我們依然可以使用之前的測試用例。下方就是我們的測試用例,與之前使用的一直,只不過需要將QuickSort這個類的對象傳給我們的測試函數即可,如下所示:
本篇博客快速排序的運行結果如下:
本篇博客對堆排序的介紹就先到這兒,下篇博客我們將會介紹“基數排序”的詳細內容。本篇博客的相關代碼依然會在github上進行分享,下方是github分享地址,如下所示:
github代碼分享地址:https://github.com/lizelu/DataStruct-Swift/tree/master/AllKindsOfSort