排序算法(2)快排

news2024/10/6 0:33:45

交换排序

思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

一、冒泡排序

 public static void BubbleSort(int[] array){
        boolean flg = false;
        for(int i = 0;i<array.length-1;i++){
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j]>array[j+1]){
                    swap(array,j,j+1);
                    flg = true;
                }
            }
            if(!flg){
                break;
            }
        }
    }

总结

1. 冒泡排序是一种非常容易理解的排序

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:稳定

 二、快速排序

基本思想:基于分治法的算法。任取待排序元素序列中的某元 素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

1、Hoare法
//快排,递归,Hoare法
    //时间复杂度最坏下O(N^2)
    //快排一般说均匀分割下复杂度优化后趋于n*logn
    public static void quickSort(int[] array){
        quick(array,0,array.length-1);
    }
    private static void quick(int[] array,int start,int end) {
        if(start>=end){
            return;
        }
        int par = partition(array,start,end);
        quick(array,start,par-1);
        quick(array,par+1,end);
    }
    private static int partition(int[] array,int left,int right){
        int i = left;
        int pivot = array[left];
        while(left<right){
            while(left<right && array[right]>=pivot){
                right--;
            }
            while(left<right && array[left]<=pivot){
                left++;
            }
            swap(array,left,right);
        }
        swap(array,left,i);

        return left;
    }

时间复杂度:最坏情况下O(N^2),如果是均匀分割下复杂度优化后趋于n*logn,快排一般用于乱序

问题:

1、堆和快排都是n*logn,那么那个更快呢?

快排还是更快一些,因为时间复杂度是粗略估计的,实际上堆排是kn*logn,最后都把k给去掉了,快排有可能是2logn,堆排是3logn。

2、与基准值比较的时候可以不写‘=’吗?

不可以!!!

3、为什么从右边开始?

如果先走左边导致最后相遇的地方是比基准大的数据,交换完后,会把大的放到了前面,不满足快排思想。

注意:因为快排是递归,数据太多的情况下会导致溢出

 2、挖坑法

 private static int partition2(int[] array,int left,int right){
       int tmp = array[left];
       while(left<right){
           while(left<right&&array[right]>=tmp){
               right--;
           }
           array[left] = array[right];
           while(left<right&&array[left]<=tmp){
               left++;
           }
           array[right] = array[left];
       }
       array[left] = tmp;
       return left;
    }
3、双指针法(了解)

 

 private static int partition3(int[] array, int left, int right) {
        int prev = left ;
        int cur = left+1;
        while (cur <= right) {
            if(array[cur] < array[left] && array[++prev] != array[cur]) {
                 swap(array,cur,prev);
            }
                cur++;
        }
        swap(array,prev,left);
        return prev;
    }
4、快速排序优化(减小递归次数)

        1. 三数取中法选key

        2. 递归到小的子区间时,可以考虑使用插入排序 

趋于有序的情况下,插入排序效率最高,并且可以减少递归次数

   private static void quick(int[] array,int start,int end) {
        if(start>=end){
            return;
        }
        if(end-start+1<=5){
            insertSortRange(array,start,end);
            return;
        }
        
        int index = midTreeNum(array,start,end);
        swap(array,index,start);
        
        int par = partition(array,start,end);
        quick(array,start,par-1);
        quick(array,par+1,end);
    }
    public static void insertSortRange(int[] array,int start,int end){
        for(int i = start+1;i<=end;i++){
            int tmp = array[i];
            int j=i-1;
            for(;j>=start;j--){
                if(array[j]>tmp){
                    array[j+1] = array[j];
                }else{
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }
    private static int partition(int[] array,int left,int right){
        int i = left;
        int tmp = array[left];
        while(left<right){
            while(left<right && array[right]>=tmp){
                right--;
            }
            while(left<right && array[left]<=tmp){
                left++;
            }
            swap(array,left,right);
        }
        swap(array,left,i);

        return left;
    }
    private static int midTreeNum(int[] array,int left,int right){
        int mid = (left+right)/2;
        //返回的是中位数的下标
        if(array[left]<array[right]){
            if (array[mid]<array[left]){
                return left;
            }else if(array[mid]>array[right]){
                return right;
            }else{
                return mid;
            }
        }else{
            if (array[mid]>array[left]){
                return left;
            }else if(array[mid]<array[right]){
                return right;
            }else{
                return mid;
            }
        }
    }
5、快排非递归

使用栈

    void quickSortNonR(int[] array) {
        Stack<Integer> stack = new Stack<>();
        int left = 0;
        int right = array.length-1;
        int par = partition(array,left,right);
        if(par>left+1){
            //如果左数只有一个值则不需要排序
            //先放左再放右
            stack.push(left);
            stack.push(par-1);
        }
        if(par<right-1){
            //先放左再放右
            stack.push(par+1);
            stack.push(right);
        }
        while(!stack.isEmpty()){
            //先取出来的是右之后是左
            right = stack.pop();
            left = stack.pop();
            par = partition(array,left,right);
            //重复最初的操作
            if(par>left+1){
                //如果左数只有一个值则不需要排序
                stack.push(left);
                stack.push(par-1);
            }
            if(par<right-1){
                stack.push(par+1);
                stack.push(right);
            }
        }
    }

 总结:

1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序

2、时间复杂度:O(N*logN)

3、空间复杂度:O(logN)(递归开空间)

4、不稳定

 例题:设一组初始记录关键字序列为(65,56,72,99,86,25,34,66),则以第一个关键字65为基准而得到的一趟快速排序结果是()  

A: 34,56,25,65,86,99,72,66             B: 25,34,56,65,99,86,72,66

C: 34,56,25,65,66,99,86,72            D: 34,56,25,65,99,86,72,66

优先尝试挖坑法,之后是Hoare法,最后双指针(很少用)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】stack queue的介绍使用以及模拟实现

目录 01.容器适配器 02.栈&#xff08;stack&#xff09; 1.stack的介绍 2.stack的使用 3.stack的模拟实现 03.队列&#xff08;queue&#xff09; 1.queue的介绍&#xff1a; 2.queue的使用 3.queue的模拟实现 04.双端队列&#xff08;deque&#xff09; 1.介绍 2.…

LeetCode1017题:负二进制转换(原创)

【题目描述】 给你一个整数 n &#xff0c;以二进制字符串的形式返回该整数的 负二进制&#xff08;base -2&#xff09;表示。注意&#xff0c;除非字符串就是 "0"&#xff0c;否则返回的字符串中不能含有前导零。 示例 1&#xff1a; 输入&#xff1a;n 2 输出&…

深度学习-N维数组和访问元素

目录 N维数组访问元素 N维数组 N维数组是机器学习和神经网络的主要数据结构 访问元素 最后一个子区域中的::是跳的意思&#xff0c;这个区域说明的是从第一个元素&#xff08;即第一行第一列那个&#xff09;对行开始跳3下循环下去直到行结束、对列开始跳2下循环下去直到列…

springboot拦载器

1、拦载器 package com.Interceptor;import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.security.auth.login.Log…

如何快速申请SSL证书实现HTTPS访问?

申请SSL证书最简单的方法通常涉及以下几个步骤&#xff0c;尽量简化了操作流程和所需专业知识&#xff1a; 步骤一&#xff1a;选择适合的SSL证书类型 根据您的网站需求&#xff0c;选择最基础的域名验证型&#xff08;DV SSL&#xff09;证书&#xff0c;它通常只需验证域名所…

技术融合与创新大象机器人水星Mercury X1人形机器人案例研究!

引言 在科技迅速发展的当下&#xff0c;人形机器人正变得日益重要&#xff0c;其应用范围从工业自动化到服务业不断扩展。本文将通过Mercury X1大象人形机器人的案例&#xff0c;探讨如何利用尖端技术如大型语言模型&#xff08;LLM&#xff09;、同时定位与映射&#xff08;SL…

雅思(IELTS)优秀小作文分享

IELTS优秀小作文分享 柱状图 本篇范文个人评分是8分或者8.5分&#xff0c;属于能找到的最优质的范文了 题目如下: The two sets of bar charts illustrate the amount of time that teenagers (boys, girls, and all) in the UK spend chatting online and playing game c…

2024 java使用Graceful Response,告别自己去封装响应,可以接收数据异常,快看我这一篇,足够你用!

参考官网手册地址&#xff1a;快速入门 | Docs 一、导入依赖&#xff08;根据springboot查看对应依赖版本&#xff09; <!-- Graceful --><dependency><groupId>com.feiniaojin</groupId><artifactId>graceful-response</artifactId&g…

GaussDB数据库事务管理

一、引言 事务管理是数据库系统中至关重要的一部分&#xff0c;它确保了数据库的一致性和可靠性。在GaussDB数据库中&#xff0c;事务管理不仅遵循传统的ACID特性&#xff0c;还提供了一些高级功能。本文将深入探讨GaussDB数据库事务管理的各个方面。 二、事务的基本概念 2.1…

CSS Position定位(详解网页中的定位属性)

目录 一、Position介绍 1.概念 2.特点 3.作用 4.应用 二、Position用法 1.position属性 2.static定位 3.fixed定位 4.relative定位 5.absolute定位 6.sticky定位 7.重叠的元素 三、CSS定位属性 四、总结 一、Position介绍 1.概念 文档流&#xff08;Document Fl…

C++ 之 string类的模拟实现

这学习我有三不学 昨天不学&#xff0c;因为昨天是个过去 明天不学&#xff0c;因为明天还是个未知数 今天不学&#xff0c;因为我们要活在当下&#xff0c;我就是玩嘿嘿~ –❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀–❀-正文开始-❀–❀–…

springboot笔记一:idea社区版本创建springboot项目的方式

社区idea 手动maven 创建springboot项目 创建之后修改pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sc…

Microsoft Edge浏览器:高效、简洁、个性化的网页浏览体验

Microsoft Edge是微软公司推出的一款网络浏览器&#xff0c;它是基于Chromium开源项目开发的&#xff0c;因此与Google Chrome有很多相似之处。以下是一些使用Microsoft Edge的心得体会&#xff1a; 1. 界面简洁&#xff1a;Microsoft Edge的界面设计非常简洁&#xff0c;用户…

R语言--图形绘制

一&#xff0c;绘制简单图形 c1<- c(10,20,30,40,50) c2<-c(2,7,15,40,50) plot(c1,c2,typeb) 具体参数请参考R语言中的绘图技巧1&#xff1a;plot()函数参数汇总_r语言plot参数设置-CSDN博客 c1<- c(10,20,30,40,50) c2<-c(2,7,15,40,50) plot(c1,c2,typeb,col#…

【北京迅为】《iTOP龙芯2K1000开发指南》-第四部分 ubuntu开发环境搭建

龙芯2K1000处理器集成2个64位GS264处理器核&#xff0c;主频1GHz&#xff0c;以及各种系统IO接口&#xff0c;集高性能与高配置于一身。支持4G模块、GPS模块、千兆以太网、16GB固态硬盘、双路UART、四路USB、WIFI蓝牙二合一模块、MiniPCIE等接口、双路CAN总线、RS485总线&#…

信息化还是数字化?

从 PC 互联网到移动互联网&#xff0c;再到物联网和最近流行的人工智能&#xff0c;科技的进步正在不断地改变着我们的生活和工作方式。这个过程实际上也是信息化和数字化的演进过程&#xff0c;许多人会问那信息化和数字化有啥区别&#xff1f;作为企业&#xff0c;如何在浪潮…

机器人操作系统ROS2学习—编译工作空间colcon build报错问题

在ROS2中&#xff0c;工作空间创建完成后&#xff0c;会经常需要编译工作空间。在工作空间dev_ws 下打开一个终端&#xff0c;通过指令Colcon build来编译工作空间。 1、这个过程有可能会出现如下错误: "colconbuild:Duplicate package names not supported" 根据…

openstack-自动化部署 9

所使用的kolla-ansible版本文档&#xff1a; Quick Start — kolla-ansible 14.10.1.dev21 documentation (openstack.org) 创建一个新的虚拟机 配置主机 安装docker 拉取openstack所需的组件镜像 安装ansible 配置ansible 启用lvm需要将另一个磁盘打成pv&#xff0c;以创建成…

如何与卫星影像叠加导出?

让每个人都有自己的地图&#xff01; 水经微图&#xff08;以下简称“微图”&#xff09;网页版&#xff0c;无需安装就可以绘制地图&#xff0c;得到了越来越多用户的亲睐。 但是&#xff0c;当我们千辛万苦绘制出来的地图&#xff0c;该如何与卫星影像叠加导出呢&#xff1…

【redis】Redis数据类型(一)——String类型(包含redis通用命令)

目录 Redis通用命令String类型常用的操作命令一些特殊命令详解setnx示例使用 setrange示例 mset示例 msetnx示例 append示例 getset示例 incr示例使用1.计数器2.限速器 bitcount示例使用&#xff1a;使用 bitmap 实现用户上线次数统计性能 String类型String类型简介String类型的…