首页 > 编程语言 >算法——初级排序算法之快速排序

算法——初级排序算法之快速排序

时间:2023-08-12 22:01:37浏览次数:37  
标签:sort arr lo 初级 算法 hi 数组 排序

介绍

快速排序可以说是应用最广泛的排序算法了,主要是因为实现简单、适用于各种不同的输入数据且在一般应用中比其他排序算法都要快得多。

快速排序是一种基于分治思想的排序算法。它将一个数组分成两个子数组,将两部分独立地排序。

原理

  • 设置两个变量 low、high,排序开始时:low=0,high=size-1。

  • 整个数组找基准正确位置,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面

特点

优点:原地排序(只需要一个很小的辅助栈),且将长度为N的数组排序所需的时间和NlgN成正比

缺点:非常脆弱,实践中需要非常小心才能避免低劣的性能

代码

package algorithm.sort;

import javax.crypto.interfaces.PBEKey;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Stream;

/**
 * 描述:快速排序
 * Created by zjw on 2021/7/4 15:38
 */
public class QuickSort {

    public static void main(String[] args) {
        Integer[] arr = Stream.generate(() -> new Random().nextInt(12))
                .limit(10).toArray(Integer[]::new);

        System.out.println("排序前 " + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后 " + Arrays.toString(arr));
    }

    public static void sort(Comparable[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    /**
     * 该方法使得数组满足下面三个条件
     * - 对于某个j, a[j]已经排定
     * - a[lo]到a[j-1]中的所有元素都不大于a[j]
     * - a[j+1]到a[hi]中的所有元素都不小于a[j]
     *
     * @param a
     * @param lo
     * @param hi
     */
    public static void sort(Comparable[] a, int lo, int hi) {
        if (hi <= lo) return;
        // if (hi <= lo + 10) { insertionSort(a, lo, hi);return; }
        int j = partition(a, lo, hi);// 切分
        sort(a, lo, j - 1); // 排序左边
        sort(a, j + 1, hi); // 排序右边
        // Quick3waySort(a, lo, hi);
    }

    /**
     * 切分
     *
     * @param a
     * @param lo
     * @param hi
     * @return
     */
    private static int partition(Comparable[] a, int lo, int hi) {
        // 将数组切分为a[lo..i-1],a[i],a[i+1..hi]
        int i = lo, j = hi + 1; // 左右指针
        Comparable v = a[lo]; // 切分元素
        while (true) {
            //检查左右是否结束并交换元素
            while (less(a[++i], v)) if (i == hi) break;
            while (less(v, a[--j])) if (j == lo) break;
            if (i >= j) break;
            exchange(a, i, j);
        }
        exchange(a, lo, j);// 将v = a[j]放入正确的位置
        return j;//a[lo..j-1]<=a[j]<=a[j+1..hi]达成
    }

    private static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }

    private static void exchange(Comparable[] a, int i, int j) {
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }

    /**
     * @param a
     * @param lo
     * @param hi
     */
    public static void insertionSort(Comparable[] a, int lo, int hi) {
        int N = a.length;
        for (int i = 0; i < N; i++) {
            // 将 a[i] 插入到 a[i-1]、a[i-2]、a[i-3]...之中
            for (int j = i; j > 0 && less(a[j], a[j - 1]); j--) {
                exchange(a, j, j - 1);
            }
        }
    }

    /**
     * 三取样切分
     * @param a
     * @param lo
     * @param hi
     */
    public static void Quick3waySort(Comparable[] a, int lo, int hi) {
        if (hi <= lo) return;
        int lt = lo, i = lo + 1, gt = hi;
        Comparable v = a[lo];
        while (i <= gt) {
            int cmp = a[i].compareTo(v);
            if (cmp < 0) exchange(a, lt++, i++);
            else if (cmp > 0) exchange(a, i, gt--);
            else i++;
        }
        // //a[lo..lt-1] < v=a[lt..gt] < a[gt+1..hi]成立
        sort(a, lo, lt - 1);
        sort(a, gt + 1, hi);
    }
}

改进

  • 小数组使用插入排序
    • 对于小数组,快速排序比插入排序慢;
    • 因为递归,快速排序的sort()方法在小数组中也会调用自己;
    • sort()中的语句if(hi <= lo) return;替换成if(hi <= lo + M){Insertion.sort(a, lo, hi);return;}小数组使用插入排序
    • 转换参数M的最佳值是和系统相关的,但是通常5~15之间的任意值在大多数情况下才能令人满意
  • 三取样切分
    • 使用小数组的一部分元素的中位数来切分数组,代价是需要计算中位数

Donate

标签:sort,arr,lo,初级,算法,hi,数组,排序
From: https://blog.51cto.com/u_11906056/7062224

相关文章

  • acwing 116.飞行员兄弟 (算法竞赛进阶指南 p48 t1 ) 题解
    原题链接https://www.acwing.com/problem/content/description/118/题目描述“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有16个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。把手可以表示为一个4х4的矩阵,您可以......
  • 算法——初级排序算法之归并排序
    介绍将两个有序的数组归并成一个更大的有序数组,这种算法叫归并排序特点优点:能够保证将任意长度为N的数组排序所需时间和NlogN成正比缺点:所需的额外空间和N成正比1、**原地归并**实现归并的一种直截了当的办法是将两个不同的有序数组归并到每三个数组中,两个数组中的元素......
  • 某公司笔试题 - 字符串排序(附python代码)
    #给定n个字符串,请对n个字符串按照字典序排列。#数据范围:1<=n<=1000,字符串长度满足1<=len<=100times=int(input("请输入字符串的个数:"))iftimes>=1andtimes<=1000:dicts={}print("请输入字符串,回车键切换输入下一个字符串:")foriinrange(......
  • 压缩算法
    思路因为这个字符串可以被多层压缩,所以我们要找到最里层的中括号。刚开始的思路是利用栈,从前往后找,遇到'['的时候,将元素入栈,遇到']'的时候,让元素出栈,计算出解压后的字符串,然后继续往后遍历,一直到栈为空。但是编码的过程中发现这种办法太过复杂。后来发现,只要从后往前遍历,找到的......
  • 【BP回归预测】基于粒子群算法优化BP神经网络实现数据回归预测附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 2023-08-12:用go语言写算法。实验室需要配制一种溶液,现在研究员面前有n种该物质的溶液,
    2023-08-12:用go语言写算法。实验室需要配制一种溶液,现在研究员面前有n种该物质的溶液,每一种有无限多瓶,第i种的溶液体积为v[i],里面含有w[i]单位的该物质,研究员每次可以选择一瓶溶液,将其倒入另外一瓶(假设瓶子的容量无限),即可以看作将两个瓶子内的溶液合并,此时合并的溶液体积和物质含量......
  • 【总结】排序算法的时间复杂度和空间复杂度
    排序算法的时间复杂度和空间复杂度最好时间复杂度最坏时间复杂度平均时间复杂度空间复杂度是否为稳定排序是否为原地排序冒泡排序$O(n)$初始数组正序$O(n^2)$初始数组逆序$O(n^2)$$O(1)$原地使用数组,无额外内存开销是是插入排序是是选择排序$O(n......
  • AXI传输总结+页面置换算法+不定态判定+PATH管理
    AXI传输总结AXI这部分我没有深入解除过,只是多多少少摸一下看下数据路径有没有传过去,总感觉不到难点在哪里,不就是一个传输协议吗?这个是soc设计方法与实现中提供的附录,可供参考,但是有版本错误(AXI4不支持写的交织,没有WID)https://www.hxedu.com.cn/hxedu/w/inputVideo.do?qid=5a79......
  • 冒泡排序
    #include<iostream>usingnamespacestd;intmain(){intt,a[4];for(inti=1;i<=3;i++){cin>>a[i];}for(inti=1;i<=2;i++){for(intj=1;j<=3-i;j++){if(a[j]<a[j+1]){t......
  • 常用的排序算法
    总结基于比较的排序(从小到大排序)冒泡排序GO实现funcMySort(arr[]int)[]int{//冒泡//大的往后冒fori:=0;i<len(arr);i++{forj:=0;j<len(arr)-1-i;j++{ifarr[j]>arr[j+1]{arr[j],arr......