轉載:https://blog.csdn.net/RUIRUI14/article/details/104304341
快速排序–三種實現方式:
快速排序運用了分治思想
① 分解
:將數組arr[ l…r ]划分為兩個子數組arr[ l…p-1 ]和arr[ p+1…r ]。使得arr[ p ]為大小居中的數,即左側arr[ l…p-1 ]中的每個元素都小於等於它;而右側arr[ p+1…r ]中的每個元素都大於等於它。其中計算下標p也是划分過程的一部分。
② 解決
:通過遞歸調用快速排序,對子數組arr[ l…p-1 ]和arr[ p+1…r ]進行排序。
③ 合並
:因為子數組都是原址排序的,所以不需要合並。即A[ l…r ]已經有序。
快排的重點在於划分區域:將小於中間值的元素全放在左邊,大於中間值的元素放在右邊
本文列出了三種快速排序的方法:
① 單向掃描分區法
② 雙向掃描分區法
③ 三指針掃描分區法
方式一:單向掃描分區法
分區方法:int single_Portion(int[] arr, int l, int r)
① 定義數組第一個元素為主元
② 定義左指針指向數組第二個元素,右指針指向數組最后一個元素(最終目的是使左指針左側都是小於等於主元的元素,右指針右側都是大於主元的元素)
③ 判斷左指針所指元素是否小於等於主元
1.若小於等於主元:左指針右移一位
2.若大於主元:將左指針所指元素與右指針所指元素交換位置,且右指針左移一位
④ 直到左指針超過右指針,此時左指針指向大於主元的第一個元素,右指針指向小於等於主元的最后一個元素
⑤ 將主元與右指針所指元素交換位置,此時即分區完畢,形成主元左側元素小於等於主元,主元右側元素大於主元
快速排序方法(遞歸實現):void single_QuickSort(int[] arr, int l, int r)
① 調用分區方法Portion(),獲取主元位置
② 將主元左側與右側分別進行快速排序,即實現了數組的排序
圖解:
方式二:雙向掃描分區法
分區方法概述(大部分與單向掃描法類似,不再贅述):int double_Portion(int[] arr, int l, int r)
① 與單向掃描分區法大體類似,區別在於:雙向掃描分區法的左指針與右指針同時掃描
② 左指針往右掃描,直到遇到第一個大於主元的元素停下;右指針往左掃描,知道遇到第一個小於等於主元的元素停下
③ 將兩指針所指元素交換位置后,兩指針繼續掃描重復②
快速排序函數:與單向掃描分區法相同void double_QuickSort(int[] arr, int l, int r)
圖解:
方式三:三指針分區法
分區方法概述:int[] tri_Portion(int[] arr, int l, int r)
① 如果數組中存在很多與主元等值的元素,那么在對主元左、右側進行快速排序時,可以不用對那些與主元等值的元素進行排序
② 增設一個等值指針,來標記第一個與主元相等的元素,最終將區域划分為三部分:
1.左側為所有小於主元的元素
2.中間為所有等於主元的元素
3.右側為所有大於主元的元素
快速排序方法概述:void tri_QuickSort(int[] arr, int l, int r)
① 將第一個等於主元的元素的左側進行快排,將最后一個等於主元的元素的右側進行快排
圖解: