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

简介: 对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理

🟡前言


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


活动地址CSDN21天学习挑战赛


🟡概述


1️⃣原理图


e47f640c764d4ca1a31fd78d2a4f863f.png


2️⃣排序原理


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


2.将大于或等于分界值的数据放到到数组右边,小于分界值的数据放到数组的左边

此时左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值


3.左边和右边的数据可以独立排序;

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


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


🟡拆分及分治思想


1️⃣拆分的解题思路


1.找一个基准值(一般是数组第一个元素),并用两个“指针”指向数组的头部和尾部

2.从右向左(从尾到头) 搜索一个比基准值小的元素,当找到时停止搜索并记录指针位置


adef11f56bae4971b0a3410ddb45def4.jpg


3.再从左到右(从头到尾)搜索一个比基准值大的元素,当找到时停止搜索并记录指针位置


1dff2e57cd3a44ceb748eda8a3f54862.jpg


4.交换左右指针的位置


7b5068626fbf4a61933018775a6cdba0.jpg


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


fa0fc80898a1407382c1712e93477ee5.png


f66bfd95fa2d4dabaad0ca72d26784f7.png


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


78408efc528d481383ba2729c04b602b.png


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;
    }


🟡调用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月前
|
搜索推荐 C语言
【排序算法】快速排序升级版--三路快排详解 + 实现(c语言)
本文介绍了快速排序的升级版——三路快排。传统快速排序在处理大量相同元素时效率较低,而三路快排通过将数组分为三部分(小于、等于、大于基准值)来优化这一问题。文章详细讲解了三路快排的实现步骤,并提供了完整的代码示例。
57 4
|
26天前
|
存储 搜索推荐 Python
用 Python 实现快速排序算法。
快速排序的平均时间复杂度为$O(nlogn)$,空间复杂度为$O(logn)$。它在大多数情况下表现良好,但在某些特殊情况下可能会退化为最坏情况,时间复杂度为$O(n^2)$。你可以根据实际需求对代码进行调整和修改,或者尝试使用其他优化策略来提高快速排序的性能
117 61
|
1月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
103 8
|
1月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
117 7
|
1月前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
53 2
|
2月前
|
搜索推荐 Shell
解析排序算法:十大排序方法的工作原理与性能比较
解析排序算法:十大排序方法的工作原理与性能比较
79 9
|
2月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
37 1
|
2月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
41 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
2月前
|
搜索推荐 Java Go
深入了解快速排序算法
深入了解快速排序算法
53 2
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
34 0