首页 > 编程语言 >基础算法篇——快速排序

基础算法篇——快速排序

时间:2022-11-02 07:44:16浏览次数:42  
标签:arr int System 算法 ints 排序 快速

基础算法篇——快速排序

本次我们介绍基础算法中的快速排序,我们会从下面几个角度来介绍快速排序:

  • 快速排序介绍
  • 暴力求解算法
  • 快速排序算法
  • 快速排序代码
  • 快速排序问题
  • 快速查找算法

快速排序介绍

我们首先来简单介绍快速排序问题:

  1. 首先我们需要确定一个分界点
这个分界点我们可以任意选择
我们常用的分界点有q[l],q[(l+r)/2],q[r]这三个点位
关于q[l]和q[r]如果选择递归的参数不合适,可能会导致死循环,我们后面会讲解,所以最好选择q[(l+r)/2]
  1. 调整区间数大小
我们希望我们选择的分界点的数作为分界数,我们不需要保证分界点的数是这个数
我们只需要保证在分界点的左侧的数全部都小于等于该分界数,同时该分界点的右侧的数全部都大于等于该分界数
  1. 递归处理
我们需要在开头进行判断:l >= r ? 

如果l >= r,那么我们就没有递归的必要,直接return即可
但是如果l > r,我们需要对其内部进行快速排序,并且在末尾处对排序后分界点的两侧再次进行递归处理

暴力求解算法

我们首先来介绍暴力求解法:

  1. 最简单最直观的方法就是采用两个数组,我们直接遍历l~r之间的所有数

  2. 如果该数小于分界数,那么放在a数组中;如果该数大于分界数,那么放在b数组中

  3. 最后我们将两个数组分别放到分界点的两侧处,然后再对其两侧进行暴力求解,最终达到效果

快速排序算法

我们采用指针来进行快速排序,因为这样不会开辟新的内存空间

我们来仔细介绍快速排序:

  1. 首先我们创建两个指针,分别指向数组的最左侧和最右侧
我们创建i和j指针,分别放于l-1和r+1处
因为我们后面需要判断该数与分界数的关系,所以我们首先移动指针再进行判断,所以我们需要将指针放在边缘处
  1. 在指针未相遇之前,我们将i向右移动,将j向左移动
首先我们需要判断两个指针没有相遇 i < j ? 

没有相遇我们开始执行排序操作:
我们进行i++,如果当前数小于分界数,我们继续移动,直到当前数大于分界数,停止移动
我们进行j--,如果当前数大于分界数,我们继续移动,直到当前数小于分界数,停止移动

当两者都停止移动时,首先需要判断 i < j ? 

若i < j 说明我们左侧停留的值大,右侧停留的值小
我们将两个数进行交换,将小的数移动到左侧,将大的数移动到右侧
  1. 递归处理
同样,我们在处理完当前数组后,需要将左侧和分界点之间的数进行排序,将分界点和右侧之间的数进行排序

快速排序代码

我们来简单实现一下快速排序算法:

import java.util.Scanner;

public class quick_sort {
    public static void main(String[] args) {
        // 输入数组的数量和数组的值

        int n;

        Scanner scanner = new Scanner(System.in);

        n = scanner.nextInt();

        int[] ints = new int[n];

        for (int i = 0 ; i < n;i++){
            ints[i] = scanner.nextInt();
        }

        // 展示数组

        System.out.print("排序前:");
        for (int i = 0; i < n; i++) {
            System.out.print(ints[i]);
        }
        System.out.println(" ");

        // 进行快速排序
        quick_sort(ints,0,n-1);

        // 展示数组

        System.out.print("排序后:");
        for (int i = 0; i < n; i++) {
            System.out.print(ints[i]);
        }
        System.out.println(" ");
    }

    public static void quick_sort(int[] ints,int l,int r){

        // 判断数组是否存在
        if (l >= r) return;

        // 进行快速排序
        int x = ints[(l+r)/2];
        int i = l-1,j = r + 1;
        while (i < j){
            // 左指针
            while (ints[++i] < x);

            // 右指针
            while (ints[--j] > x);

            // 如果左右指针没有相遇进行交换
            if (i < j){
                int temp = ints[i];
                ints[i] = ints[j];
                ints[j] = temp;
            }
        }

        // 实现递归处理
        quick_sort(ints,l,j);
        quick_sort(ints,j+1,r);
    }
}

快速排序问题

我们前面说到我们选择分界点的时候尽量选择(r+l)/2,因为单l或单r可能会导致死循环

下面我们给出示例:

import java.util.Scanner;

public class quick_sort {
    public static void main(String[] args) {
        // 输入数组的数量和数组的值

        int n;

        Scanner scanner = new Scanner(System.in);

        n = scanner.nextInt();

        int[] ints = new int[n];

        for (int i = 0 ; i < n;i++){
            ints[i] = scanner.nextInt();
        }

        // 展示数组

        System.out.print("排序前:");
        for (int i = 0; i < n; i++) {
            System.out.print(ints[i]);
        }
        System.out.println(" ");

        // 进行快速排序
        quick_sort(ints,0,n-1);

        // 展示数组

        System.out.print("排序后:");
        for (int i = 0; i < n; i++) {
            System.out.print(ints[i]);
        }
        System.out.println(" ");
    }

    public static void quick_sort(int[] ints,int l,int r){

        // 判断数组是否存在
        if (l >= r) return;

        // 进行快速排序
        int x = ints[l];
        int i = l-1,j = r + 1;
        while (i < j){
            // 左指针
            while (ints[++i] < x);

            // 右指针
            while (ints[--j] > x);

            // 如果左右指针没有相遇进行交换
            if (i < j){
                int temp = ints[i];
                ints[i] = ints[j];
                ints[j] = temp;
            }
        }

        // 实现递归处理
        quick_sort(ints,l,i-1);
        quick_sort(ints,i,r);
    }
}

下面我们模拟操作:

我们传入数据: 2 1 2

我们的分界数为: 1
最开始数组为:1 2

我们的i指针停在0处,我们的j指针也停在0处
这时我们进行第二轮递归处理

quick_sort(ints,0,-1)左侧递归直接结束
quick_sort(ints,0,1)右侧递归和第一轮完全相同,所以我们会一直循环下去

快速查找算法

我们在快速排序的基础上研究出了快速查找算法

题目:

  • 给定一个长度为n的整数数列,以及一个整数k,请用最快选择算法求出数列的第k小的数是多少

求解方法:

  • 我们根据快速排序算法来将数组进行排序,舍弃掉左右两侧的一侧,对另一侧进行查找排序,递归即可

求解代码:

import java.util.Scanner;

public class eee {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        // 输入总数
        int n = scanner.nextInt();

        // 输入查找第k小的值
        int k = scanner.nextInt();

        // 输入数组
        int[] arr = new int[n];

        for (int i  = 0; i < arr.length; i++) {
            arr[i] = scanner.nextInt();
        }

        // 运行方法查找第k小的值
        int minK = findMinK(arr,0,n-1, k);

        // 输出
        System.out.println(arr[minK]);
    }

    public static int findMinK(int[] arr,int l,int r,int k){

        // 如果相等,说明找到了
        if (l >= r) return l;

        // 下面是标准的快速排序
        int x = arr[(l+r)/2];
        int i = l-1;
        int j = r+1;

        while (i < j){

            while (arr[++i] < x);
            while (arr[--j] > x);

            if (l < r){
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        // 如果数在左侧,对左侧遍历;如果数在右侧,对右侧遍历并修改概述在右侧的k值
        if (j > k) return findMinK(arr,l,j,k);
        else return findMinK(arr,j+1,r,k-j+1);
    }

}

结束语

好的,关于基础算法篇的快速排序就介绍到这里,希望能为你带来帮助~

标签:arr,int,System,算法,ints,排序,快速
From: https://www.cnblogs.com/qiuluoyuweiliang/p/16849770.html

相关文章

  • 快速安装swoole的办法
    方法一:使用pecl快速安装soole如果特别慢,那么就需要设置代理#设置代理pearconfig-sethttp_proxyhttp://127.0.0.1:8015peclchannel-updatehttps://pecl.ph......
  • 代码随想录算法训练营第七天|454、四数相加Ⅱ|383、赎金信|15、三数之和|18、四数之和
    454、四数相加Ⅱ·map哈希表当初不知四数相加的好,做完四数之和发现~oh这题真简单题目链接:https://leetcode.cn/problems/4sum-ii/前提:计算四个数组中多少个元组满......
  • 如何实现一个LRU算法
    ​ 首先,什么是LRU算法呢?全称是:Leastrecentlyused,也就是最近最旧未被使用的算法。其核心思想就是:最近被访问到的数据,在未来也可能被访问到。 所以按照LRU算法来说,数......
  • 代码随想录算法训练营第六天| 242.有效的字母异位词,349. 两个数组的交集 ,202. 快乐数,1
    哈希表:用来快速判断一个元素是否出现在集合里 哈希表是根据关键码的值而直接进行访问的数据结构。(关键码也就是数组的下标,元素通过计算生成一个标识,此标识就是数组的下......
  • 快速了解Java设计模式
    背景Java二十三种设计模式的简单介绍,目的是能看懂别人写的设计模式代码,且能应用常用的设计模式。设计模式分类创建型模式工厂方法(Factory)工厂模式分为三种:简单工厂(不......
  • 基数排序
    基数排序基数排序(桶排序)介绍:基数排序(radixsort)属于“分配式排序”(distributionsort),又称“桶子法”(bucketsort)或binsort,顾名思义,它是通过键值的各个位的值,将要......
  • 数据结构 二叉排序树的代码实现
    7.8、二叉排序树(BST)二叉排序树又称二叉查找树左子树上所有结点的值都小于根结点的值右子树上所有结点的值都大于根结点的值左子树和右子树又是一颗二叉排序树左子树......
  • 数据结构 玩转数据结构 5-6 递归算法的调试
    0课程地址https://coding.imooc.com/lesson/207.html#mid=13442 1重点关注1.1递归算法的调试打印日志层级调试参考3.1 2课程内......
  • Java实现优化版【快速排序】+四度优化详解
    参考书目:《大话数据结构》一:快速排序1.基本思想:通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续......
  • 数据结构中的七大排序算法—2
        今天为大家带来的是数据结构中的七大排序算法的其中两种:希尔排序和堆排序。本次的代码实现还是使用的C语言,编译器还是vs2013版本,希望接下来的内容可以帮助大家理......