快速排序的三种分区方法

转载: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)
  ① 将第一个等于主元的元素的左侧进行快排,将最后一个等于主元的元素的右侧进行快排

图解:

posted @ 2020-10-22 19:54  喵喵队立大功  阅读(1337)  评论(0编辑  收藏  举报