zoukankan      html  css  js  c++  java
  • 18、排序算法-快速排序

    来源:https://www.bilibili.com/video/BV1B4411H76f?p=60

    一、思路

    快速排序:是交换排序中的一种,属于冒泡排序的改进方法。在数据中间找到一个基准值,如果想从小到大排列,比基准值小的放在基准值的左边,比基准值大的放在基准值的右边。然后左边右边分别递归快速排序。

    例如:[-9,78,0,23,-576,70],从小到大排列

    方法开始设置左边的起始位置下标l = 0,右边的起始位置下标r = arr.length-1,以及基准值,基准值可以在数组中随意选择,这里选择的是pivot=arr[(l+r)/2],即数组中间位置的数据作为基准值。

    第一趟:从l和r分别开始找比基准值小(右边)和大(左边)的数据。

    这里基准值是0。-9小于0,l++,在左边找到了比0大的数78,此时l=1;

    继续在右边找,70大于0,r--,在右边找到了比0小的数-576,此时r=4。

    交换两个数[-9,-576,0,23,78,70]。此时l=1所在的位置已经小于基准值,l++,到0了,l=2;

    继续右边,r=4所在的位置已经大于基准值,r--,r=3的位置数据依然大于基准值,r--,此时r=2=l。本次左右两边的数据比较完毕,结束。

    左边[-9,780],0,[23,78,70]右边。

    第二趟,以同样的形式递归左边和右边。以下都是这样。

    这样说不清楚,一会单步调试看一下。

     

    二、实现

     1 //快速排序
     2 public class QuickSort {
     3     public static void main(String[] args) {
     4         int[] arr = {-8,-9,78,0,23,-567,70,-7};
     5         System.out.println(Arrays.toString(arr));
     6         int left = 0;
     7         int right = arr.length - 1;
     8 
     9         quickSort(arr,left,right);
    10         System.out.println(Arrays.toString(arr));
    11     }
    12 
    13     public static void quickSort(int[] arr,int left,int right){
    14         int l = left;//左边的起始位置
    15         int r = right;//右边的起始位置
    16         int pivot = arr[(left+right)/2];//中间值(基准值)
    17         while(l < r){
    18             //遍历左边找比基准值大的
    19             while (arr[l] < pivot){
    20                 l += 1;
    21             }
    22             //遍历右边找比基准值小的
    23             while (arr[r] > pivot){
    24                 r -= 1;
    25             }
    26             if(l >= r){
    27                 //此次比较已经完全遍历了整个数组
    28                 break;
    29             }
    30             //找到了对应的数据,交换
    31             int temp = arr[l];
    32             arr[l] = arr[r];
    33             arr[r] = temp;
    34 
    35             //还有一种可能,遍历到了基准值,同样满足跳出上面两个while的条件,基准值也要交换
    36             //交换完成后,基准值的位置发生了改变
    37             if(arr[l] == pivot){
    38                 //这个基准值是从右边换过来的
    39                 r -= 1;
    40             }
    41             if(arr[r] == pivot){
    42                 //这个基准值是从左边换过来的
    43                 l += 1;
    44             }
    45         }
    46 
    47         //接下来开始迭代了,但是要避免一个情况,l和r最终在一个位置,那么递归会重复中间的数据
    48         if(l == r){
    49             l += 1;
    50             r -= 1;
    51         }
    52         if(left < r){
    53             quickSort(arr,left,r);
    54         }
    55         if(right > l){
    56             quickSort(arr,l,right);
    57         }
    58     }
    59 }

    结果

    [-8, -9, 78, 0, 23, -567, 70, -7]
    [-567, -9, -8, -7, 0, 23, 70, 78]

    单步调试:

    第一次进入方法

    找到左边的坐标(2)和右边的坐标(7),交换数据后[-8, -9, -7, 0, 23, -567, 70, 78]

     下一波,左边(3),右边(5),左边到基准值的位置了,依然交换[-8, -9, -7,  -567, 23,0, 70, 78]

     

     这时候下边的判断就有用了,基准值交换到了右边,所以左边的继续++(4),继续和基准值比较,交换

     下一波,左(4),右(5),还是交换[-8, -9, -7,  -567,0,23, 70, 78],但是基准值换到了左边,所以右边--(4)再与基准值比。但是r=4也满足下面的判断,所以l++(5)

     好了,现在满足退出while的条件了,整个数组遍历完成了,继续下去就是迭代的过程了。

  • 相关阅读:
    Linux 开发之线程条件锁那些事
    Linux 开发之线程条件锁那些事
    Linux 开发之线程条件锁那些事
    洛谷3919:可持久化数组——题解
    洛谷3919:可持久化数组——题解
    洛谷3919:可持久化数组——题解
    洛谷3919:可持久化数组——题解
    长篇干货|以太坊智能合约 —— 最佳安全开发指南(附代码)
    长篇干货|以太坊智能合约 —— 最佳安全开发指南(附代码)
    长篇干货|以太坊智能合约 —— 最佳安全开发指南(附代码)
  • 原文地址:https://www.cnblogs.com/zhao-xin/p/13163225.html
Copyright © 2011-2022 走看看