• 算法排序6——快速排序(分治思想)


    🟡前言

    21天挑战赛第二周。本文主要讲述有关快速排序的内容

    活动地址:CSDN21天学习挑战赛

    🟡概述

    1️⃣原理图

    在这里插入图片描述

    2️⃣排序原理

    1. 首先设定一个分界值 ,通过该分界值将数组分成左右两部分

    2. 将大于或等于分界值的数据放到到数组右边,小于分界值的数据放到数组的左边
      此时左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值

    3. 左边和右边的数据可以独立排序;
      对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理

    4. 重复上述过程,当左侧和右侧两个部分的数据排完序后,整个数组的排序也就完成了

    🟡拆分及分治思想

    1️⃣拆分的解题思路

    1. 找一个基准值(一般是数组第一个元素),并用两个“指针”指向数组的头部和尾部
    2. 从右向左(从尾到头) 搜索一个比基准值小的元素,当找到时停止搜索并记录指针位置

    在这里插入图片描述

    1. 从左到右(从头到尾)搜索一个比基准值大的元素,当找到时停止搜索并记录指针位置
      在这里插入图片描述

    2. 交换左右指针的位置
      在这里插入图片描述

    3. 重复上述步骤,直至左右指针指向同一个元素

    在这里插入图片描述
    在这里插入图片描述

    2️⃣拆分中分治思想体现

    在这里插入图片描述

    3️⃣拆分的代码实现

        public static int partition(Comparable[]a, int lo, int hi){
            //确定分界值
            Comparable key = a[0];
            //定义两个指针
            int left = lo;
            int right = hi + 1;
            //拆分数组
            while (true){
                //从右往左移动指针,当遇到元素值比key小就停止
                while (less(key, a[--right])){
                    if(right == lo){
                        break;
                    }
                }
                //从左往右移动指针,当遇到元素值比key大就停止
                while (less(a[++left], key)){
                    if (left == hi) {
                        break;
                    }
                }
    			//当指针指向同一元素时结束循环
                if(left >= right){
                    break;
                }
                //当左边的元素值更大时,交换两者位置
                else {
                    exch(a,left,right);
                }
            }
            //当完成拆分后,交换当前分界值的指针与首个元素对应的指针
            exch(a, lo, right);
            return right;
        }
    
    • 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

    🟡调用API实现快速排序

    1️⃣构造方法和成员方法

    构造方法
    Quick();

    成员方法

    • public static void sort(Comparable[]a):对数组a中元素进行排序
    • public static boolean less(Comparable x, Comparable y):判断x是否小于y
    • public static void exch(Comparable[]a, int i, int j):交换数组a中下标为 i 和 j 的元素
    • public static int partition(Comparable[]a, int lo, int hi):对数组a中索引从lo到hi之间元素分组,返回分组界限对应索引
    • public static void sort(Comparable[]a, int lo, int hi):对数组a中从索引lo到索引hi之间元素进行排序

    2️⃣解题思路

    1. 定义less方法用来比较元素大小
    2. 定义exch方法用来交换数组内元素
    3. 定义一个sort方法来对数组内元素排序
    4. 定义一个partition方法来对数组进行拆分排序
    5. 定义一个sort的重载方法,并在方法内调用sort方法对子组排序(递归)

    3️⃣完整代码

    public class QuickSort {
    
        private static void exch(Comparable[] a, int i, int j){
            Comparable temp;
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    
        public static boolean less(Comparable x, Comparable y){
            return x.compareTo(y) < 0;
    
        }
    
        public static void sort(Comparable[] a){
            int lo = 0;
            int hi = a.length-1;
            sort(a,lo,hi);
        }
    
        public static void sort(Comparable[]a, int lo, int hi){
            //安全性校验
            if(hi <= lo){
                return;
            }
            //调用方法对数组进行分组
            int partition = partition(a, lo, hi);
            //对左子数组排序
            sort(a,lo,partition-1);
            //对右子数组排序
            sort(a,partition+1,hi);
        }
    
        public static int partition(Comparable[]a, int lo, int hi){
            //确定分界值
            Comparable key = a[0];
            //定义两个指针
            int left = lo;
            int right = hi + 1;
            //拆分数组
            while (true){
                //从右往左移动指针,当遇到元素值比key小就停止
                while (less(key, a[--right])){
                    if(right == lo){
                        break;
                    }
                }
                //从左往右移动指针,当遇到元素值比key大就停止
                while (less(a[++left], key)){
                    if (left == hi) {
                        break;
                    }
                }
    
                if(left >= right){
                    break;
                }
                //当左边的元素值更大时,交换两者位置
                else {
                    exch(a,left,right);
                }
            }
            //当完成拆分后,交换分界值
            exch(a, lo, right);
            return right;
        }
    }
    
    
    • 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
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    🟡结语

    快速排序利用了递归和分治思想来实现,至此所有的排序都已经讲解完毕,接下来是有关链表的知识

  • 相关阅读:
    7.21 - 每日一题 - 408
    高级词汇和句子(二)-day15
    H5实现预览pdf(PC+移动端都可以)
    OpenCV-Mat类-图像表示
    mysql根据逗号将一行数据拆分成多行数据,并展示其他列
    结构性设计模式之装饰器模式
    unity属性之UnityEngine
    使用CEF(七)详解macOS下基于CEF的多进程应用程序CMake项目搭建
    【Python】Python写入电子表格
    spring中注解的作用
  • 原文地址:https://blog.csdn.net/Alita233_/article/details/126246359