【八大排序(三)】快速排序

❣博主主页: 33的博客❣
▶️文章专栏分类:八大排序◀️
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你了解更多排序知识

在这里插入图片描述

目录

  • 1.前言
  • 2.快速排序
    • 2.1概念
    • 2.2画图理解
    • 2.3递归代码实现
      • 2.3.1Hoare法
      • 2.3.2挖坑法
      • 2.3.3前后指针法
      • 2.3.4优化
    • 2.4非递归代码实现
  • 3.总结

1.前言

关于排序的知识,我们已经介绍了直接插入排序,希尔排序,选择排序和堆排序,这篇文章博主就继续和大家分享快速排序的知识。

2.快速排序

2.1概念

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割城两个子序,左子序中的元素均小于基准值,右子序的元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

2.2画图理解

选择排序

2.3递归代码实现

2.3.1Hoare法

在这里插入图片描述

 public int[] quickOrder(int[] arr){
        int p=0;
        quick(0,arr.length-1,arr);
        return arr;
    }
    private void quick(int start, int end, int[] arr) {
    if (start>=end){
        return;
    }
    int p=partionHoare(start,end,arr);
    quick(start,p-1,arr);
    quick(p+1,end,arr);
    }
    public int partionHoare(int l,int r,int[] arr){
        int tmp=l;
        while (l<r){
            while (l<r&&arr[l]<arr[tmp]){
                l++;
            }
            while (r>l&&arr[r]>arr[tmp]){
                r--;
            }
            swap(l,r,arr);
        }
        //l==r
        swap(l,tmp,arr);
        return l;
    }

2.3.2挖坑法

在这里插入图片描述

    private void quick(int start, int end, int[] arr) {
    if (start>=end){
        return;
    }
    int p=partitionHole(start,end,arr);
    quick(start,p-1,arr);
    quick(p+1,end,arr);
    }
    public int partitionHole(int l,int r,int[] arr){
        int tmp=arr[l];
        while (l<r){
            if (l<r&&arr[r]>tmp){
                r--;
            }
            arr[l]=arr[r];
            if (l<r&&arr[l]<tmp){
                l++;
            }
            arr[r]=arr[l];
        }
        arr[l]=tmp;
        return l;
    }

2.3.3前后指针法

在这里插入图片描述

private void quick(int start, int end, int[] arr) {
    if (start>=end){
        return;
    }
    int p=partition(start,end,arr);
    quick(start,p-1,arr);
    quick(p+1,end,arr);
    }
private  int partition( int left, int right,int[] array) {
        int prev = left ;
        int cur = left+1;
        while (cur <= right) {
            if(array[cur] < array[left] && array[++prev] != array[cur]) {
                swap(cur,prev,array);
            }
            cur++;
        }
        swap(prev,left,array);
        return prev;

2.3.4优化

观察上述代码,我们发现我们的基准值都是第一个元素,如果一个了比较有序的数组,我们进行快排,就可能形成当分支的树,所有我们要堆基准值进行优化,选取最左边,最右边元素和中间元素比较大小,把值为中间的作为基准元素。

   public int[] quickOrder(int[] arr){
        int p=0;
        quick(0,arr.length-1,arr);
        return arr;
    }
    private void quick(int start, int end, int[] arr) {
    if (start>=end){
        return;
    }
    if (end-start>=15){
        insertOrder(start,end,arr);
        return;
    }
    int m=mid(start,end, arr);
    swap(start,m,arr);
   
    int p=int p=partitionHole(start,end,arr);
    quick(start,p-1,arr);
    quick(p+1,end,arr);
    }
    public void insertOrder(int l,int r ,int[] arr){
        for (int i=l+1;i<=r;i++){
            int tmp=arr[i];
            int j=i-1;
            for (;j>=0;j--){
                if(arr[j]>tmp){
                    arr[j+1]=arr[j];
                }else break;
            }
            arr[j+1]=tmp;
        }
    }
    public  int mid(int l,int r,int[] arr){
       int mid=(l+r)/2;
       if (arr[l]<arr[r]){
           if(arr[mid]<arr[l]){
               return l;
           }else if (arr[mid]>arr[r]){
               return r;
           }else {
               return mid;
           }
       }else {
           //arr[l]>=arr[r]
           if (arr[mid]>arr[l]){
               return l;
           }else if (arr[mid]<arr[r]){
               return r;
           }else {
               return mid;
           }
       }
    }
    public int partitionHole(int l,int r,int[] arr){
        int tmp=arr[l];
        while (l<r){
            if (l<r&&arr[r]>tmp){
                r--;
            }
            arr[l]=arr[r];
            if (l<r&&arr[l]<tmp){
                l++;
            }
            arr[r]=arr[l];
        }
        arr[l]=tmp;
        return l;
    }   

2.4非递归代码实现

在这里插入图片描述

public int[] quickOrderNor(int[] arr){
        Stack<Integer> stack=new Stack<>();
        int s=0;
        int e=arr.length-1;
        int pivot=partitionHole(s,e,arr);
        if (pivot-1>s){
            stack.push(s);
            stack.push(pivot-1);
        }
        if (e-1>pivot){
            stack.push(pivot+1);
            stack.push(e);
        }
        while (!stack.isEmpty()){
             e=stack.pop();
             s=stack.pop();
             pivot=partitionHole(s,e,arr);
            if (pivot-1>s){
                stack.push(s);
                stack.push(pivot-1);
            }
            if (e-1>pivot){
                stack.push(pivot+1);
                stack.push(e);
            }
        }
    return arr;
    }

时间复杂度:
最好的情况下:O(N
logN)
最坏情况下:O(N^2) 逆序/有序
空间复杂度:
最好的情况下:O(logN)
最坏情况下:O(N) 逆序/有序
稳定性:不稳定
*

3.总结

快速排序是一个比较重要的排序算法,它可以用多种方法来实现,但不同方法的时间复杂度和空间复杂度。

下期预告:归并排序

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/586843.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

外包干了3天,技术就明显退步了。。。。。

先说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

一个完全免费、私有且本地运行的搜索聚合器-FreeAskInternet

什么是 FreeAskInternet FreeAskInternet 是一个完全免费、私有且本地运行的搜索聚合器&#xff0c;使用 LLM 生成答案&#xff0c;无需 GPU。用户可以提出一个问题&#xff0c;系统将使用 searxng 进行多引擎搜索&#xff0c;并将搜索结果组合到 ChatGPT3.5 LLM 中&#xff0…

第三节课,功能2:开发后端用户的管理接口-- postman--debug测试

一、如何使用postman 网址&#xff1a; https://www.postman.com/downloads/ 【Postman小白教程】五分钟学会如何使用Postman~_哔哩哔哩_bilibili postman安装使用_bowser agent在postman哪里-CSDN博客 二、下载后 登录&#xff0c;开始测试 2.1 关于postman 报错&#…

什么是 Web3 的生成式 AI?

从 Web 1.0 的静态、单向通信到 Web 2.0 的动态、用户驱动的格局&#xff0c;互联网在二十年的时间里经历了一场显着的转变。现在&#xff0c;当我们站在 Web 3.0 时代的边缘时&#xff0c;我们正在见证更具颠覆性的事物的曙光&#xff1a;生成式人工智能 (AI) 融入我们的数字世…

【数据结构(邓俊辉)学习笔记】向量05——排序器

文章目录 0. 概述1.统一入口2. 起泡排序2.1 起泡排序&#xff08;基础版&#xff09;2.1.1 算法分析2.1.2 算法实现2.1.3 重复元素与稳定性2.1.4 复杂度分析 3. 归并排序3.1 有序向量的二路归并3.2 分治策略3.3 实例3.4 二路归并接口的实现3.5 归并时间3.6 排序时间 4.综合评价…

【Linux】体系结构和进程管理

目录 一、认识冯诺依曼体系结构 1.1 概念 1.2 组成 1.3 存储分级 1.4 有关冯诺依曼的问题 二、操作系统 2.1 概念和功能 2.2 如何理解操作系统的 "管理" 2.3 操作系统的用户、系统调用和库函数概念 三、进程 3.1 基本概念 3.2 描述进程-进程控制块PCB …

C语言:数据结构(双向链表)

目录 1、双向链表的结构2、顺序表和双向链表的优缺点分析3、双向链表的实现 1、双向链表的结构 注意&#xff1a;这⾥的“带头“跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在单链表阶段称呼不严谨&#xff0c;但是为了更好的理解就直接称为单链表的头节点。 带…

QT之信号和槽

在刚刚了解Qt的时候&#xff0c;为了通过按钮显示 hello world 的时候曾说明过信号与槽&#xff0c;虽然没有细说&#xff0c;不过也算是接触过。 而本文就会细细说明什么是 Qt 的信号与槽。 概念初识 在 linux 学进程相关的内容的时候&#xff0c;曾了解过信号是操作系统控…

【STM32】快速使用F407通用定时器输出可变PWM

网上的文章太啰嗦&#xff0c;这里直接开始。 使用的是STM32CubeIDE&#xff0c;HAL。以通用定时器TIM12在 通道2上输出1KHz的PWM为例。 要确定输出的引脚、定时器连接在哪里。 TIM2、3、4、5、12、13、14在APB1上&#xff0c;最大计数频率84M。 TIM1、8、9、10、11在APB2…

Python 与 TensorFlow2 生成式 AI(二)

原文&#xff1a;zh.annas-archive.org/md5/d06d282ea0d9c23c57f0ce31225acf76 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;教授网络生成数字 在前一章中&#xff0c;我们涵盖了神经网络模型的构建基块。在这一章中&#xff0c;我们的第一个项目…

HIVE启动步骤

不如意的时候不要尽往悲伤里钻 想想有笑声的日子 启动HIEV 1.启动虚拟机Hadoop集群 2.连接Linux 3.start-all.sh 4.hive 5.hive启动时报错 当我们启动Hadoop集群时 启动hive可能会出现卡在true处不动的情况 那么我们只需要做一个操作就可以解决问题啦 hdfs haadmin -transitio…

ASP.NET数据存储与交换系统设计

摘 要 该系统以Microsoft Visual Studio 2003作为开发工具&#xff0c;选用SQL Server 2000数据库来实现数据存储&#xff0c;并设计开发了一种基于B/S模式的数据存储与交换系统。该系统完成了用户注册管理、后台管理和用户空间管理功能&#xff1b;为每个用户提供了个人的存…

数据库(MySQL)—— DQL语句(基本查询和条件查询)

数据库&#xff08;MySQL&#xff09;—— DQL语句&#xff08;基本查询和条件查询&#xff09; 什么是DQL语句基本查询查询多个字段字段设置别名去除重复记录 条件查询语法条件 我们今天进入MySQL的DQL语句的学习&#xff1a; 什么是DQL语句 MySQL中的DQL&#xff08;Data Q…

【ARM 裸机】NXP 官方 SDK 使用

在前几节中&#xff0c;学习了如何编写汇编的 led 驱动、C 语言的 led 驱动、模仿 STM32 进行开发&#xff0c;我们都是自己写外设寄存器的结构体&#xff0c;外设非常的多&#xff0c;写起来费时费力&#xff0c;NXP 针对 I.MX6ULL 编写了一个 SDK 包&#xff0c;这个 SDK 包就…

python的输入输出(爽文,备忘,查询,友好)

Python中的输入输出主要涉及到输入函数和输出函数。 输出函数&#xff1a;print() print() 函数用于将信息输出到屏幕上。它可以输出字符串、变量的值&#xff0c;以及其他各种数据类型。 name "Alice" age 30 print("姓名:", name, "年龄:&quo…

OpenCV如何实现背投(58)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV直方图比较(57) 下一篇&#xff1a;OpenCV如何模板匹配(59) 目标 在本教程中&#xff0c;您将学习&#xff1a; 什么是背投以及它为什么有用如何使用 OpenCV 函数 cv::calcBackP…

轻松下载小程序短剧视频,你不可错过的神器!

探索小程序的精彩短剧&#xff0c;一款神器让您的收藏变得触手可及。轻松下载&#xff0c;无损享受&#xff0c;每个精彩瞬间&#xff0c;都不让你错过。让这款下载神器成为你掌中的宝藏&#xff0c;开启随时随地的精彩观影体验。 这个神器就是下载高手 下载小程序视频的工具…

GoLang Gin实际使用

所有代码同步到Admin/gitDemo - Gitee.comhttps://gitee.com/mec-deployment-team_0/git-demo/tree/dev/ 1.创建Gin框架 一般设计一个常规的web项目&#xff0c;都需要以下几个模块 runApp 主函数&#xff0c;运行整个项目routes 路由控制&#xff0c;管理跳转以及路由分组co…

CTF-Show nodejs

web334 下载附件&#xff0c;有两个文件 在Character.toUpperCase()函数中&#xff0c;字符ı会转变为I&#xff0c;字符ſ会变为S。 在Character.toLowerCase()函数中&#xff0c;字符İ会转变为i&#xff0c;字符K会转变为k。 所以用ctfſhow 123456登录就可以出flag了 w…

力扣刷题第一天:消失的数字

大家好啊&#xff0c;从今天开始将会和大家一起刷题&#xff0c;从今天开始小生也会开辟新的专栏。&#x1f61c;&#x1f61c;&#x1f61c; 目录 第一部分&#xff1a;题目描述 第二部分&#xff1a;题目分析 第三部分&#xff1a;解决方法 3.1 思路一&#xff1a;先排序…