• 快速排序详解


    题目

    对于数组使用快速排序算法进行排序
    输入
    [6,1,2,7,9,3,4,5,10,8]
    输出
    [1,2,3,4,5,6,7,8,9,10]

    解析

    假设我们现在对数据arr[6,1,2,7,9,3,4,5,10,8]这个10个数进行排序。
    首先在这个序列中随便找一个数作为基准数。选取第一个数6作为基准数。在这个序列中,将所有比基准数大的数放在6的右边,比基准数小的数放在6的左边,类似下面这种排列:[3,1,2,5,4,6,9,7,10,8]
    在初始状态下,数字6在序列的第1位。我们的目标是将6挪到序列中间的某个位置,假设这个位置是k。现在就需要寻找这个k,并且以第k位为分界点,左边的数都小于等于6,右边的数都大于等于6。
    具体步骤如下

    1. 使用指针i,j分别从左向右找大于6的数、从右向左找小于6的数。注意每次都是j先移动,找到满足条件的数后再移动i
      在这里插入图片描述

    2. 查找到符合条件的数arr[3],arr[7],交换二者
      在这里插入图片描述

    3. 继续移动i,j找到第二组满足条件的数,并交换二者
      在这里插入图片描述

    4. 继续移动i,j,先移动j,j=5,arr[j]=3,再移动i,i右移后与j重叠,终止移动。由于j先移动,此时停止有两种情况要么j移动到i要么j找到了小于基准数6的值,所以终止后将arr[j]与基准数交换
      在这里插入图片描述

    5. 至此第一轮探测结束,得到以6为基准数、左侧均小于6右侧均大于6的数组。以6为分界点,对6两边数组重复执行上述操作,直至排序出所有数据
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hkRYF3oO-1657007254427)(img_6.png)]

    6. 得到最终排序结果
      在这里插入图片描述

    编码

    	public static void main(String[] args) {
            int[] arr = {6,1,2,7,9,3,4,5,10,8};
            print("输入",arr);
            quickSort(arr,0,arr.length-1);
            print("输出",arr);
        }
    
    
        private static void quickSort(int[] arr, int left, int right) {
            // 起始大于终止时结束
            if(left>right){
                return;
            }
            int i = left;
            int j = right;
            int base = arr[left];
            while(i<j){
                // 右指针向左查找大于等于基准数的值
                while(i<j && arr[j] >= base){
                    j--;
                }
                // 左指针向右查找小于等于基准数的值
                while(i<j && arr[i]<=base){
                    i++;
                }
                // 如果左指针小于右指针,执行交换
                if(i<j){
                    swap(arr,i,j,base);
                }
            }
            // 由于每次都是右指针先移动,那么上面循环终止条件要么j找到了小于等于基准数的值要么j=i,此时arr[j]一定小于等于基准数,执行交换
            if(left<i){
                swap(arr,left,i,base);
            }
            // 递归执行基准数左侧数组
            quickSort(arr,left,j-1);
            // 递归执行基准数右侧数组
            quickSort(arr,j+1,right);
        }
    
        private static void swap(int[] arr,int i,int j,int base){
            System.out.println("");
            print("执行交换[base="+base+",i="+i+",j="+j+"]");
            print("交换前",arr);
            int temp = arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
            print("交换后",arr);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    运行结果

    执行交换[base=6,i=3,j=7]
    交换前:[6,1,2,7,9,3,4,5,10,8]
    交换后:[6,1,2,5,9,3,4,7,10,8]
    
    执行交换[base=6,i=4,j=6]
    交换前:[6,1,2,5,9,3,4,7,10,8]
    交换后:[6,1,2,5,4,3,9,7,10,8]
    
    执行交换[base=6,i=0,j=5]
    交换前:[6,1,2,5,4,3,9,7,10,8]
    交换后:[3,1,2,5,4,6,9,7,10,8]
    
    执行交换[base=3,i=0,j=2]
    交换前:[3,1,2,5,4,6,9,7,10,8]
    交换后:[2,1,3,5,4,6,9,7,10,8]
    
    执行交换[base=2,i=0,j=1]
    交换前:[2,1,3,5,4,6,9,7,10,8]
    交换后:[1,2,3,5,4,6,9,7,10,8]
    
    执行交换[base=5,i=3,j=4]
    交换前:[1,2,3,5,4,6,9,7,10,8]
    交换后:[1,2,3,4,5,6,9,7,10,8]
    
    执行交换[base=9,i=8,j=9]
    交换前:[1,2,3,4,5,6,9,7,10,8]
    交换后:[1,2,3,4,5,6,9,7,8,10]
    
    执行交换[base=9,i=6,j=8]
    交换前:[1,2,3,4,5,6,9,7,8,10]
    交换后:[1,2,3,4,5,6,8,7,9,10]
    
    执行交换[base=8,i=6,j=7]
    交换前:[1,2,3,4,5,6,8,7,9,10]
    交换后:[1,2,3,4,5,6,7,8,9,10]
    输出:[1,2,3,4,5,6,7,8,9,10]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    两万字盘点被玩烂了的9种设计模式
    第六章(4):Python的函数———作用域(scope)
    Windows Service Wrapper 一个将可执行文件封装为windows服务的工具
    前端面试题,精简版本
    qt 调用qt_material库后自定义进度条样式
    Questasim与Visualizer的livesim仿真
    黑马Java热门面试题Web(四)
    SystemVerilog Assertions应用指南 Chapter1.40SVA与功能覆盖
    MySQL常用脚本
    iTOP-RK3568开发板内核模块实验-设置交叉编译器
  • 原文地址:https://blog.csdn.net/u014395955/article/details/125621508