快速排序(图解详细流程)

快速排序(图解详细流程)基本思想是 从一个数组中随机选出一个数 N 通过一趟排序将数组分割成三个部分 1 小于 N 的区域 2 等于 N 的区域 3 大于 N 的区域 然后再按照此方法对小于区的和大于区分别递归进行 从而达到整个数据变成有序数组 图解流程下面通过实例数组进行排序 存在以下数组从上面的数组中 随机选取一个数 假设这里选的数是 5 与最右边的 7 进行交换 nbsp 如下图准备一个小于区和大于区 大于区包含最右侧

基本思想是:从一个数组中随机选出一个数N,通过一趟排序将数组分割成三个部分,1、小于N的区域 2、等于N的区域 3、大于N的区域,然后再按照此方法对小于区的和大于区分别递归进行,从而达到整个数据变成有序数组。

图解流程

下面通过实例数组进行排序,存在以下数组

快速排序(图解详细流程)

从上面的数组中,随机选取一个数(假设这里选的数是5)与最右边的7进行交换 ,如下图

快速排序(图解详细流程)

准备一个小于区和大于区(大于区包含最右侧的一个数)等于区要等最后排完数才会出现,并准备一个指针,指向最左侧的数,如下图

快速排序(图解详细流程)

 到这里,我们要开始排序了,每次操作我们都需要拿指针位置的数与我们选出来的数进行比较,比较的话就会出现三种情况,小于,等于,大于。三种情况分别遵循下面的交换原则

  • 1 指针的数
    <选出来的数< span="">

    •  1.1 拿指针位置的数与小于区右边第一个数进行交换
    •  1.2 小于区向右扩大一位
    •  1.3 指针向右移动一位
  • 2 选出来的数=选出来的数
    • 2.1 指针向右移动一位
  • 3 指针的数>选出来的数
    • 3.1 拿指针位置的数与大于区左边第一个数进行交换
    • 3.2 大于区向左扩大一位
    • 3.3 指针位置不动

根据上面的图可以看出5=5,满足交换原则第2点,指针向右移动一位,如下图

快速排序(图解详细流程)

 从上图可知,此时3<5,根据交换原则第1点,拿3和5(小于区右边第一个数)交换,小于区向右扩大一位,指针向右移动一位,结果如下图

快速排序(图解详细流程)

 从上图可以看出,此时7>5,满足交换原则第3点,7和2(大于区左边第一个数)交换,大于区向左扩大一位,指针不动,如下图

快速排序(图解详细流程)

从上图可以看出,2<5,满足交换原则第1点,2和5(小于区右边第一个数)交换,小于区向右扩大一位,指针向右移动一位,得到如下结果

快速排序(图解详细流程)

从上图可以看出,6>5,满足交换原则第3点 ,6和6自己换,大于区向左扩大一位,指针位置不动,得到下面结果

快速排序(图解详细流程)

此时,指针与大于区相遇,则将指针位置的数6与随机选出来的5进行交换,就可以得到三个区域:小于区,等于区,大于区,如下: 

快速排序(图解详细流程)

 到此,一趟排序结束了,后面再将小于区和大于区重复刚刚的流程即可得到有序的数组

快排的时间复杂度O(N*logN),空间复杂度O(logN) 【因为每次都是随机事件,坏的情况和差的情况,是等概率的,根据数学期望值可以算出时间复杂度和空间复杂度】,不稳定性排序

代码 

理解了上面的流程后,看代码会比较轻松,下面代码都做了注释,方便理解

 public static void quickSort(int[] arr, int L, int R) { if (L < R) { //生成一个随机数 double random = Math.random(); //在L至R位置随机选取一个数与最右边的数交换 swap(arr, L + (int) (random * (R - L + 1)), R); //此数组长度永远为2,p[0]为等于区的左边界,p[1]为等于区的右边界 int[] p = partition(arr, L, R); //将分出来的小于区重复上面的动作 quickSort(arr, L, p[0] - 1); //将分出来的大于区重复上面的动作 quickSort(arr, p[1] + 1, R); } } public static int[] partition(int[] arr, int L, int R) { //声明一个小于区的索引 int less = L - 1; //声明一个大于区的索引 int more = R; //声明一个起始索引指针 int index = L; //划分原则: /*1 如果arr(index) 
  
    arr(R) 3.1 拿index位置的数与大于区左边第一个数进行交换 3.2 大于区向左扩大一位 3.3 index索引位置不动 */ while (index < more) { if (arr[index] < arr[R]) { //一行代码完成划分原则的1.1, 1.2, 1.3功能 swap(arr, index++, ++less); } else if (arr[index] == arr[R]) { index++; } else { //一行代码完成划分原则的3.1, 3.2, 3.3功能 swap(arr, index, --more); } } //如果index索引与more相遇,则退出循环,并且R位置数与more位置数交换 swap(arr, more, R); //用来记录等于区的左边界和右边界对应的索引 return new int[]{less + 1, more}; } //将数组中索引i和j的数进行交换 public static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } 
  

 

 

 

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/178484.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午5:11
下一篇 2026年3月26日 下午5:12


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号