排序算法(2)快排

交换排序

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

一、冒泡排序

 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法,最后双指针(很少用)

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

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

相关文章

Sarcasm detection论文解析 | 通过阅读进行讽刺推理-Reasoning with sarcasm by reading in-between

论文地址 论文地址&#xff1a;[1805.02856] Reasoning with Sarcasm by Reading In-between (arxiv.org) 论文首页 笔记大纲 通过阅读进行讽刺推理论文笔记 &#x1f4c5;出版年份:2018&#x1f4d6;出版期刊:&#x1f4c8;影响因子:&#x1f9d1;文章作者:Tay Yi,Luu Anh…

FIR滤波器——DSP学习笔记三(包含一个滤波器设计的简明案例)

​​​​​​ 背景知识 FIR滤波器的特性与优点 可精确地实现线性相位响应&#xff08;Linear phase response&#xff09;&#xff0c;无相位失真&#xff1b; 总是稳定的&#xff0c;所有极点都位于原点 线性相位FIR滤波器的性质、类型及零点位置 冲击响应满足&#xff1a;奇…

挺看好的一位实习生,顶峰见!

大家好&#xff0c;我是程序员鱼皮。今天我要分享自己团队里一位全栈实习生的实习总结。 在实习期间&#xff0c;这位同学参与了多个项目的工作&#xff0c;包括企业动态公告系统的开发、企业周边系统的搭建、撰写技术教程、开发 IDEA 插件、构建云端管理平台等等。 实习近 3…

个人学习总结__打开摄像头、播放网络视频的以及ffmpeg推流

前言 最近入手了一款非常便宜的usb摄像头&#xff08;买回来感觉画质很低&#xff0c;没有描述的4k&#xff0c;不过也够用于学习了&#xff09;,想着利用它来开启流媒体相关技术的学习。第一步便是打开摄像头&#xff0c;从而才能够对它进行一系列后续操作&#xff0c;诸如实…

网动统一通信平台存在任意文件读取漏洞

声明&#xff1a; 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 简介 网动统一通信平台&#xff08;ActiveUC&#xff09…

AEMTO--一种自适应进化多任务优化框架

AEMTO–一种自适应进化多任务优化框架 title&#xff1a; Evolutionary Multitask Optimization With Adaptive Knowledge Transfer author&#xff1a; Hao Xu, A. K. Qin, and Siyu Xia. journal&#xff1a; IEEE TRANSACTIONS ON EVOLUTIONARY COMPUTATION (TEVC) DOI&…

基于SpringBoot+Vue校园竞赛管理系统的设计与实现

项目介绍&#xff1a; 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;竞赛信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行…

B2B商城系统如何搭建?

相较于单个商家的独立商城&#xff0c;B2B商城系统凭借诸多优势成为电商领域中最受关注的一种模式。目前在政府、金融、汽车、跨境等行业领域都有广泛应用。那么&#xff0c;B2B商城系统如何搭建呢&#xff1f;我们从开发语言、功能模块、优势来进行分析。 一、B2B商城系统开发…

对抗攻击新手实战

实战核心思想&#xff1a; 训练x(输入&#xff09;&#xff0c;让第一次训练好的&#xff0c;正确的y去和我们想要误导机器去识别的类别的那个y做一个损失函数【loss torch.mean(y[:, 248])】&#xff0c;不同的是&#xff0c;我们其实希望是一个梯度上升&#xff0c;给图片加…

31 OpenCV 距离变换和分水岭算法

文章目录 距离变换分水岭算法distanceTransform 距离变换watershed 分水岭算法示例 距离变换 分水岭算法 distanceTransform 距离变换 void cv::distanceTransform (InputArray src,OutputArray dst,int distanceType,int maskSize,int dstType CV_32F) src:输入图像&#xf…

一篇关于Cookie的基础知识

目录 一、现有问题 二、简介 三、Cookie原理 四、Cookie应用 4.1 创建并向客户端发送Cookie 4.2 从客户端读取Cookie 4.3 Cookie的生命周期 4.4 Cookie的编码和解码 4.5 优缺点 五、记录上次登录的时间&#xff08;案例&#xff09; 六、Cookie 获取范围有多大&…

Python —— 模块、包

一、模块和包 1. 模块module 模块是 Python 程序架构的一个核心概念。Python中模块就是一个.py文件&#xff0c;模块中可以定义函数&#xff0c;变量&#xff0c;类。模块可以被其他模块引用 1.1. 创建模块文件 创建文件&#xff1a;utils.py # 定义变量 name 张三# 定义函…

Qt绘图与图形视图之场景、视图架构的简单介绍

往期回顾 Qt绘图与图形视图之绘图技术知识点的简单介绍-CSDN博客 Qt绘图与图形视图之常见图形、路径、文字、图片的绘制介绍-CSDN博客 Qt绘图与图形视图之移动鼠标手动绘制任意多边形的简单介绍-CSDN博客 Qt绘图与图形视图之场景、视图架构的简单介绍 一、GraphicsView 1、存…

项目部署总结

1、安装jdk 第一步&#xff1a;上传jdk压缩安装包到服务器 第二步&#xff1a;将压缩安装包解压 tar -xvf jdk-8uXXX-linux-x64.tar.gz 第三步&#xff1a;配置环境变量 编辑/etc/profile文件&#xff0c;在文件末尾添加以下内容&#xff1a; export JAVA_HOME/path/to/j…

12:HAL----I2C

目录 一:I2C通信协议 1:I2C简历 2:硬件电路 3:I2C时序基本单元 A : 开/ 终条件 2:发送一个字节 3:接收一个字节 4:应答机制 4:I2C时序 1:指定地址写 2:当前地址读 3: 指定地址读 二&#xff1a;HAL库 A&#xff1a;轮询方式 B:中断方式 三:案例 A:轮询方式-…

代码随想录算法训练营第12天:滑动窗口和前缀和

代码随想录算法训练营第12天&#xff1a;滑动窗口和前缀和 这里我参考了西法的博客&#xff0c; 467. 环绕字符串中唯一的子字符串(中等)795. 区间子数组个数(中等)904. 水果成篮(中等)992. K 个不同整数的子数组&#xff08;困难&#xff09;1109. 航班预订统计(中等) 前四…

第G9周:ACGAN理论与实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 由于ACGAN的原理在上一篇文章中已经很详细的解释过了&#xff0c;这次我们直接上代码 一、代码解读 import argparse import os import numpy as npimport t…

视频批量下载工具

1、功能演示 该工具实现了某个人主页视频批量下载&#xff0c;最多支持一次下载50个视频&#xff0c;这50个选取的是最新发布的50个视频&#xff0c;视频为高清的1080p&#xff0c;并直接将视频保存到本地。 2、软件使用介绍 2.1 解压 拿到工具软件后&#xff0c;首先是对软件…

什么是外汇爆仓?怎样避免?

外汇爆仓是指当交易者的保证金低于特定比例时&#xff0c;经纪商会自动平仓一个或所有的开仓头寸。避免外汇爆仓的关键在于合理配置资金、设置止损、适度交易、顺势而为以及调整心态。 外汇爆仓是外汇交易中的一种风险控制机制。当交易者的账户净值低于已用保证金的特定比例时&…

AI图书推荐:《企业AI转型:如何在企业中部署ChatGPT?》

Jay R. Enterprise AI in the Cloud. A Practical Guide...ChatGPT Solutions &#xff08;《企业AI转型&#xff1a;如何在企业中部署ChatGPT&#xff1f;》&#xff09;是一本由Rabi Jay撰写、于2024年由John Wiley & Sons出版的书籍&#xff0c;主要为企业提供实施AI转型…