排序算法-快速排序

2023-09-14 16:19:50

属性

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

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

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

代码及注释(递归写法)

public static void quickSort(int[]arr){
        quick1(arr,0,arr.length-1);
    }

    private static void quick(int[]arr,int begin,int end){
        //出递归
        if(begin>=end){
            return;
        }
        //由于参考值的取值要尽量取数据的中间值,所以我们可以拿begin,end和mid下标的中间值来作为参考值
        //获得了中间值的下标tmpIndex
        int tmpIndex=threeMid(arr,begin,end);
        //将中间值交换到第一个位置作为参考值
        swap(arr,begin,tmpIndex);
        //进行数据的划分,将小于参考值的数据放到左边,大于参考值的数据放到右边
        //得到划分好数据后,参考值最终放到的位置(参考值排序后的下标)
        int rid=parttion1(arr,begin,end);
        //以同样的方式划分参考值左边和右边的数据
        quick(arr,begin,rid-1);
        quick(arr,rid+1,end);
    }

    //进行begin-end范围内数据的划分,将小于参考值的数据放到左边,大于参考值的数据放到右边
    private static int parttion1(int[]arr,int begin,int end){
        //用挖坑法进行划分
        int tmp=arr[begin];
        while (begin<end){
            //现在begin下标相当于已经没有数据了,是一个坑,要通过end下标找到一个比参考值小的值放到这个坑中
            while (begin<end&&arr[end]>=tmp){
                end--;
            }
            //跳出了上面的循环说明找到了一个比参考值小的数据
            //将数据放到坑中
            arr[begin]=arr[end];
            //现在end下标相当于已经没有数据了,是一个坑,要通过begin下标找到一个比参考值大的值放到这个坑中
            while (begin<end&&arr[begin]<=tmp){
                begin++;
            }
            //跳出了上面的循环说明找到了一个比参考值大的数据
            //将数据放到坑中
            arr[end]=arr[begin];
        }

        //当begin和end指向一个下标时便退出了循环,而他们指向的这个下标是一个坑(没有数据)
        //将参考值放到这个坑中
        arr[begin]=tmp;
        //返回参考值所在的下标,方便去划分参考值左边和右边的数据
        return begin;
    }

//在array数组中找到下标begin,mid,end的中间值
    private static int threeMid(int[] array,int begin,int end){
        int mid=(begin+end)/2;
        if(array[begin]>array[end]){
            if(array[end]>array[mid]){
                return end;
            }
            else if(array[mid]>array[begin]){
                return begin;
            }
            else {
                return mid;
            }
        }
        else {
            if (array[mid]>array[end]){
                return end;
            } else if (array[begin]>array[end]) {
                return begin;
            }
            else {
                return mid;
            }
        }
    }

    private static void swap(int[] array,int m,int n){
        int tmp=array[m];
        array[m]=array[n];
        array[n]=tmp;
    }

代码及注释(非递归写法)

        其实非递归写法的思路和递归相同,只是非递归要自己创建一个栈来模拟出递归的效果而已

 //非递归实现快速排序
    public static void quickSortNoRrcur(int[] array) {
        //当排序的数目小于一定范围时直接用插入排序
        if(array.length<5){
            InsertSort insertSort=new InsertSort();
            insertSort.insertSort(array);
            return;
        }

        Stack<Integer> stack=new Stack<>();
        int start=0;
        int end=array.length-1;
        //三数取中
        int midIndex=threeMid(array, start, end);
        //把三个数中位于中间的值放到第一位
        swap(array,start,midIndex);
        //挖坑法将比array[begin]小的放左边,大的放右边
        int rid=parttion(array, start, end);

        //判断是否满足入栈条件
        if(rid>start+1){
            stack.push(start);
            stack.push(rid-1);
        }
        if(rid<end-1){
            stack.push(rid+1);
            stack.push(end);
        }

        while (!stack.empty()){
            end=stack.pop();
            start=stack.pop();

            //当排序的数目小于一定范围时直接用插入排序
            if(end-start+1<5){
                InsertSort insertSort=new InsertSort();
                insertSort.insertSort(array);
                return;
            }

            //三数取中
            midIndex=threeMid(array, start, end);
            //把三个数中位于中间的值放到第一位
            swap(array,start,midIndex);
            //挖坑法将比array[begin]小的放左边,大的放右边
            rid=parttion(array, start, end);

            //判断是否满足入栈条件
            if(rid>start+1){
                stack.push(start);
                stack.push(rid-1);
            }
            if(rid<end-1){
                stack.push(rid+1);
                stack.push(end);
            }
        }
    }

    private static int threeMid(int[] array,int begin,int end){
        int mid=(begin+end)/2;
        if(array[begin]>array[end]){
            if(array[end]>array[mid]){
                return end;
            }
            else if(array[mid]>array[begin]){
                return begin;
            }
            else {
                return mid;
            }
        }
        else {
            if (array[mid]>array[end]){
                return end;
            } else if (array[begin]>array[end]) {
                return begin;
            }
            else {
                return mid;
            }
        }
    }

    private static void swap(int[] array,int m,int n){
        int tmp=array[m];
        array[m]=array[n];
        array[n]=tmp;
    }

更多推荐

关于 firefox 不能访问 http 的解决

情景:我在虚拟机192.168.x.111上配置了DNS服务器,在kali上设置192.168.x.111为DNS服务器后,使用firefox地址栏搜索域名www.xxx.com,访问在192.168.x.111搭建的网站,本来经192.168.x.111DNS服务器解析后,应该访问的是http://www.xxx.c

数据在内存中的存储

文章目录一、整数在内存中的存储二、大小端引言大小端的介绍三、浮点数在内存中的存储储存规则取的过程一、整数在内存中的存储计算机中有3中二进制存储方法,即原码、补码、反码正整数的原码、反码、补码都相同负整数原码、反码、补码各不相同:原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。反码:将原码的符号位不变,其他位

华为数通方向HCIP-DataCom H12-831题库(单选题:81-100)

第81题关于结构化的网络故障排除流程中的确认故障阶段的描述,正确的是?A、应关注如何更好的解决故障而不论该故障是否属于自己的负责范围。B、应重视用户的意见,以用户的判断为依据来判断故障问题C、应使影响最小化,尽量不让其他人知道网络出现了故障。D、应确认排障工作是否属于自己的负责范围答案:D解析:当网络出现故障时,首先应

iOS技术博主指南:填写苹果应用上架中的隐私政策信息

摘要:本文将详细介绍iOS技术博主在苹果应用上架过程中如何填写隐私政策信息。博主可以通过AppStoreConnect为应用程序提供隐私政策网址和用户隐私选项网址,并了解如何填写隐私政策文本。本文将提供步骤和注意事项,帮助博主顺利完成隐私政策信息的填写。引言:为了保护用户的隐私权益,苹果要求所有上架的应用程序必须提供隐

计算机视觉与深度学习-全连接神经网络-训练过程-欠拟合、过拟合和Dropout- [北邮鲁鹏]

目录标题机器学习的根本问题过拟合overfitting泛化能力差。应对过拟合最优方案次优方案调节模型大小约束模型权重,即权重正则化(常用的有L1、L2正则化)L1正则化L2正则化对异常值的敏感性随机失活(Dropout)随机失活的问题欠拟合机器学习的根本问题机器学习的根本问题是优化与泛化问题。优化:是指调节模型以在训练

Arcgis提取每个像元的多波段反射率值

Arcgis提取每个像元的多波段反射率值数据预处理数据预处理阶段需要对遥感图像进行编辑传感器参数、辐射定标、大气校正、正射校正,具体流程见该文章裁剪研究区对于ENVI处理得到的tiff影像,虽然是经过裁剪了,但是还存在黑色的背景值,此时需要用按掩膜提取的方法删除研究区以外的部分。该方法的具体流程在文章中提到然后还需要对

【C++】map,set简单操作的封装实现(利用红黑树)

文章目录一、STL中set与map的源码二、红黑树结点的意义三、仿函数的妙用四、set,map定义迭代器的区别五、map,set迭代器的基本操作:1.begin()end()2.operator++3.operator--六、迭代器拷贝构造特殊处理7.源码RBTree.h2.MyMap.h3.MySet.h一、STL中

贝叶斯人工智能大脑与 ChatGPT

文章目录一、前言二、主要内容🍉CSDN叶庭云:https://yetingyun.blog.csdn.net/一、前言论文地址:https://arxiv.org/abs/2308.14732这篇论文旨在研究ChatGenerativePre-trainedTransformer(ChatGPT)在贝叶斯推理情况下解

List与ArrayList

目录一、List及其使用1.1List的概念1.2常见接口的介绍1.3List的使用二、线性表和顺序表2.1线性表2.2顺序表三、ArrayList介绍四、ArrayList的使用4.1ArrayList构造4.2ArrayList的常用方法4.3ArrayList的遍历4.4ArrayList的扩容机制五、Array

三分钟图解事务隔离级别

详细见:三分钟图解事务隔离级别,看一遍就懂数据库中事务指的是什么“锁"是数据库系统区别于文件系统的一个关键特性,其对象是事务,用来锁定的是数据库中的对象,如表、页、行等。锁确实提高了并发性,但是却不可避免地存在一些潜在的并发一致性问题。不过好在锁只会带来四种问题(丢失更新、脏读、不可重复读、幻读),如果可以防止这四种情

项目设计集合(人工智能方向):助力新人快速实战掌握技能、自主完成项目设计升级,提升自身的硬实力(不仅限NLP、知识图谱、计算机视觉等领域)

优质项目专栏:提升自身的硬实力:汇总有意义的项目设计集合,助力新人快速实战掌握技能,助力用户更好利用CSDN平台,自主完成项目设计升级,提升自身的硬实力。专栏订阅:项目大全提升自身的硬实力资料合集更优惠第一期资料合集:https://download.csdn.net/download/sinat_39620217/8

热文推荐