前言
推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。
快速排序
快速排序由C.A.R.Hoare在1962年提出,是氣泡排序的一種改進。其基本思想為:通過一趟排序將待排序資料分割成獨立的兩部分,其中一部分的所有值都比另一部分的所有值都小,然後再對分割的兩部分分別進行快速排序,整個過程可以遞迴進行,最終所有資料變為有序序列。
排序要點
設待排序陣列為a[0],a[1],...a[n-1],快速排序步驟為:
- 初始化兩個變數i、j,剛開始i=1,j=n-1。
- 將第一個元素a[0]作為基準數。
- 從i開始向後搜尋,找到第一個大於基準數的元素a[i]。
- 從j開始向前搜尋,找到第一個小於基準數的元素a[j]。
- 將a[i]與a[j]互換。
- 重複3到5步驟,直到i=j,然後將a[0]與a[j-1]對換。
- 序列被基準數分割成兩個分割槽,前面分割槽全部小於基準數,後面分割槽全部大於基準數。
- 遞迴對分割槽子序列進行快速排序,最終完成整個排序工作。
每趟快速排序的核心工作是:選一個元素作為基準數,然後將所有比它小的數都放到它前面,大於它的都放在它後面。
排序過程
假設我們有如下8個元素,分別為59, 25, 71, 16, 62, 84, 34,45
,現在進行快速排序。

初始化變數i=1,j=7,並且將第一個元素a[0]作為基準數,然後開始從i向後尋找第一個大於a[0]的元素,59先與25比較,

由於25小於59,所以往後移一步繼續比較,

71大於59,找到第一個大於59的元素。接著我們從j開始向前搜尋,尋找第一個小於基準數的元素,59與45比較,45小於59,於是找到第一個小於基準數的元素,

此時對換a[i]與a[j]的值,即71與45對調,發現對調的效果了嗎?就是將大的甩後面,小的向前推。

繼續尋找下一個大於基準數的元素,將i向後一步,16小於59,

i再往後移一步,此時62大於59,找到大於59的元素了。接著j向前尋找第一個小於基準數的元素,

34小於59,於是找到要找的元素,

此時對換a[i]與a[j]的值,即62與34對調,

繼續尋找下一個大於基準數的元素,將i向前後一步,84大於59,找到,

而j向前尋找,發現與i已經重合了,停止繼續往前比較,

直接將重合位置的前一個元素的值與基準數對換,即a[j-1]與a[0]的值對調,也就是34與59對調。至此,完成第一趟快速排序。

接下去準備第二趟快速排序,第一趟執行完後,基準數將序列分成兩個分割槽,而待排序物件就是上一次基準數前面的那些元素,即59前面的元素。
對於該子序列,初始時i=0,j=3,這一趟基準數a[0]為34。然後開始從i向後尋找第一個大於a[0]的元素,34先與25比較,

由於25小於34,所以往後移一步繼續比較,此時45大於34,找到第一個大於基準數的元素,

接著j向前尋找第一個小於基準數的元素,16小於34,它即是要找的元素。

此時對換a[i]與a[j]的值,即45與16對調,

繼續尋找下一個大於基準數的元素,將i向前後一步,發現與j已經重合了,停止繼續往後比較,

直接將重合位置的前一個元素的值與基準數對換,即a[j-1]與a[0]的值對調,也就是34與16對調。至此,完成第二趟快速排序。

接下去準備第三趟快速排序,基準數34將序列又分成兩個分割槽,對其前一分割槽繼續進行處理。
此時該分割槽子序列只有16和25兩個元素,初始時i=1,j=1,基準數a[0]為16。一開始i和j就重合了,此時的i找到大於基準數的元素,而j沒找到小於基準數的元素,所以不對換。

接下去準備第四趟快速排序,在第一趟執行完後,先處理的是59前面的分割槽,現在接著處理59後面的分割槽。這個處理順序是由遞迴處理方式決定的。
對於後面分割槽子序列,初始時i=6,j=7,該子序列的第一個元素作為基準數,即84。然後開始從i向後尋找第一個大於a基準數的元素,84先與62比較,

由於62小於84,所以往後移一步,此時也到達序列最末尾,此時71小於84,未能找到大於基準數的元素。接著j向前尋找小於基準數的元素,71小於84,找到該元素。

然後將71與基準數84對換,完成第四趟快速排序。

接下去準備第五趟快速排序,基準數84只有前面一個分割槽,對該分割槽子序列繼續進行處理。
此時該分割槽子序列只有71和62兩個元素,初始時i=6,j=6,基準數為71。一開始i和j就重合了,此時i找不到大於基準數的元素,而j找到了小於基準數的元素,

於是將71和62進行對換,完成第五趟快速排序。至此,整個序列都完成排序工作。

-------------推薦閱讀------------
我的開源專案彙總(機器&深度學習、NLP、網路IO、AIML、mysql協議、chatbot)
跟我交流,向我提問:

歡迎關注:
