快速排序和归并排序哪个快?

news2025/1/16 21:47:58

两个排序的基本思想都是分治(分而治之),实现一般都使用递归实现。

1.快速排序

双边指针(交换法):记录分界值 ,创建左右指针(记录下标)。

  1. 以第一个元素为分界值,先从右向左找出比分界值小的数据,然后从左向右找出比分界值大的数据;

  1. 左右指针下标未过界,交换左右指针数据;

  1. 循环查找交换,直到左右指针下标重合(这时右边都是比重合处大的数据,左边除了分界值都是比重合处小的数据),重合后交换分界值和重合下标数据,重合下标变为新分界值,再分别递归处理新分界值左右部分数据。

public void quickSort(int[] arr, int startIndex, int endIndex) {
    if (startIndex >= endIndex) {
        return;
    }
    // 找到分界值
    int pivotIndex = doublePointerSwap(arr, startIndex, endIndex);
    // 用分界值下标区分出左右区间,进行递归调用
    quickSort(arr, startIndex, pivotIndex - 1);
    quickSort(arr, pivotIndex + 1, endIndex);
}

private int doublePointerSwap(int[] arr, int startIndex, int endIndex) {
    int pivot = arr[startIndex];
    int leftPoint = startIndex;
    int rightPoint = endIndex;

    while (leftPoint < rightPoint) {
        // 从右向左找出比pivot小的数据
        while (leftPoint < rightPoint
                && arr[rightPoint] > pivot) {
            rightPoint--;
        }
        // 从左向右找出比pivot大的数据
        while (leftPoint < rightPoint
                && arr[leftPoint] <= pivot) {
            leftPoint++;
        }
        // 没有过界则交换
        if (leftPoint < rightPoint) {
            int temp = arr[leftPoint];
            arr[leftPoint] = arr[rightPoint];
            arr[rightPoint] = temp;
        }
    }
    // 最终将分界值与当前指针数据交换
    arr[startIndex] = arr[rightPoint];
    arr[rightPoint] = pivot;
    // 返回分界值所在下标
    return rightPoint;
}

2.归并排序

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

public int[] mergeSort(int[] nums, int low, int high) {
    if (low == high) return new int[] { nums[low] };

    int mid = (low + high)/ 2;
    int[] leftArr = mergeSort(nums, low, mid); //左有序数组
    int[] rightArr = mergeSort(nums, mid + 1, high); //右有序数组
    int[] newNum = new int[leftArr.length + rightArr.length]; //新有序数组

    int m = 0, i = 0, j = 0;
    while (i < leftArr.length && j < rightArr.length) {
        newNum[m++] = leftArr[i] <= rightArr[j] ? leftArr[i++] : rightArr[j++];
    }
    while (i < leftArr.length)
        newNum[m++] = leftArr[i++];
    while (j < rightArr.length)
        newNum[m++] = rightArr[j++];
    return newNum;
}

3.比较

  1. 归并排序的比较次数小于快速排序的比较次数;移动(赋值)次数一般多于快速排序的移动次数。

  1. 归并排序的内存占用高于快速排序,快速排序时原地排序,空间复杂度为O(1),归并排序不是原地排序,数组合并需要额外空间。

  1. 快速排序是边分解边排序,每次分解都实现整体上有序,即参照数左侧的数小于参照值,右侧的大于参照值;归并排序是先递归分解到最小区间,然后从小区间开始合并排序,是自下而上的排序。

  1. 快速排序是不稳定的,时间复杂度在O(nlogn)~O(n^2)之间,归并排序是稳定的,时间复杂度是O(nlogn)。

哪个更快?

  1. C++毫无疑问是快速排序(C++有很强的inline优化机制,比较操作比赋值操作要快的多)。

  1. Java有点复杂,基本数据类型如(int/double),快排更快;复杂数据类型(对象)则不一定,有可能归并排序快,也有可能快排快,取决于比较和赋值操作哪个更快。

下面代码就可以测试出部分情况赋值操作比较比较操作更快。

    public static void main(String[] args) {
        int assignmentFast = 0;
        for(int k=0; k<100; k++){
            int len = 1024 * 1024 ;
            NumTest[] numArray = new NumTest[len];
            for(int i=0; i<numArray.length; i++){
                NumTest numTest = new NumTest();
                numTest.setNum1(RandomUtil.getNum(1,9999));
                numTest.setNum2(RandomUtil.getNum(1,9999));
                numArray[i] = numTest;
            }
            long startTime = System.currentTimeMillis();
            for(int i=0; i<numArray.length; i++){
                if(numArray[0].compareTo(numArray[i]) > 0){}
            }
            long compareSpend = System.currentTimeMillis()-startTime;

            startTime = System.currentTimeMillis();
            for(int i=0; i<numArray.length; i++){
                numArray[0] = numArray[i];
            }
            long moveSpend = System.currentTimeMillis()-startTime;
            if(moveSpend < compareSpend){
                assignmentFast++;
                System.out.println("赋值比比较操作快,赋值花费时间:"+moveSpend+",比较花费时间:"+compareSpend);
            }
        }
        System.out.println("赋值比比较快的次数:"+ assignmentFast);
    }

    static class NumTest implements Comparable<NumTest>{
        int num1;
        int num2;

        public int getNum1() {
            return num1;
        }

        public void setNum1(int num1) {
            this.num1 = num1;
        }

        public int getNum2() {
            return num2;
        }

        public void setNum2(int num2) {
            this.num2 = num2;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            NumTest numTest = (NumTest) o;
            return num1 == numTest.num1 &&
                    num2 == numTest.num2;
        }

        @Override
        public int hashCode() {
            return Objects.hash(num1, num2);
        }

        @Override
        public int compareTo(NumTest o) {
            int otherSum = o.getNum1() + o.getNum2();
            int localSum = num1 + num2;
            if(localSum == otherSum){
                return 0;
            }
            return localSum>otherSum?1:-1;
        }
    }

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

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

相关文章

C语言指针变量作为函数参数

在C语言中&#xff0c;函数的参数不仅可以是整数、小数、字符等具体的数据&#xff0c;还可以是指向它们的指针。用指针变量作函数参数可以将函数外部的地址传递到函数内部&#xff0c;使得在函数内部可以操作函数外部的数据&#xff0c;并且这些数据不会随着函数的结束而被销毁…

ocelot的单节点解决方案

ocelot的问题前面我们解决了consul的单节点的集群扩建。这里讨论如果在多客户端访问时&#xff0c;单网关也会有瓶颈。如果单台挂掉&#xff0c;那么也会麻烦&#xff0c;所以根据项目需要解决问题。ocelot多节点部署最简单的粗暴解决&#xff0c;多部署几台网关。但是我们需要…

mac环境和windows环境下GeoServer如何安装部署

geoserver是从事GIS行业都应当了解的一个gis服务器。 所以说学会geoserver是一个非常必要的事情。那么这篇文章呢我就带着大家来一起学习如何在Mac机器上和windows机器上安装并部署Geoserver。 首先不管是哪个环境我们都需要去官网上先下载安装包。 第一步我们要去geoserver的…

【计算机组成原理】y = a * b + c 的执行具体流程

文章目录1.2.2 认识各个硬件部件1. 主存储器的基本组成2. 运算器的基本组成3. 控制器的基本组成4. 计算机的工作流程1.2.2 认识各个硬件部件 1. 主存储器的基本组成 存储体&#xff1a;存放数据和指令地址寄存器&#xff1a;用来存放读取存储体数据时存放的具体位置数据寄存器…

12、字符(串)输入、输出

目录 一、字符数据输入&#xff0f;输出 1. 字符数据输入 2. 字符数据输出 二、字符串输入&#xff0f;输出 1. 字符串输入函数 2. 字符串输出函数 一、字符数据输入&#xff0f;输出 1. 字符数据输入 字符数据输入使用的是getchar函数&#xff0c;其作用是从终端&…

前端遇到的问题

inputs-outputs https://angular.cn/guide/inputs-outputs 用于父组件与子组件间的值传递 在项目中引入核心组件 父组件在其html界面绑定属性 在子组件里通过Input传递值 具体里: 使用默认规则数组绑定固定值(比如id)的错误 这里两个ts文件之间传值,采用了一个get函数,…

微信小程序 view组件的基本使用

1.view基本理论 能看图就尽量减少文字提示&#xff0c;从图书可以看出ABC是纵向排列的。 为什么会纵向排列而不是横向排列&#xff0c;那是因为view是块元素&#xff0c;能占满整一行。 怎么让view块元素横向并排呢&#xff1f; 向上图一样横向排列&#xff0c;接下来教学从0…

Kerberos协议与认证数据包分析

Kerberos协议 Kerberos是一种在开放的非安全网络中认证并识别用户身份信息的方法, 它旨使用密钥加密技术为客户端/服务端应用程序提供强身份认证。 目前主流的Kerberos版本是2005年的RFC4120标准的Kerberos v5, Windows、Linux和MacOs均支持Kerberos协议。Kerberos基础 Kerbe…

Quartz入门看这一篇文章就够了

第一章 Quartz简介 第一节 Quartz是什么? 1Quartz [kwɔːts]是一个完全由Java编写的开源的作业调度框架第二节 Quartz可以用来做什么? 比如说买火车票下单之30分钟之后,查看是否付款付款完成之后,在乘车日期的时候是否乘车或者每个月1号扣房贷每个月20号自动还信用卡想定时…

为什么要使用采购管理软件 采购管理软件推荐

在企业发展道路上&#xff0c;采购部门是一个非常重要的组织&#xff0c;它会直接影响到企业的经济效益。企业在采购活动中&#xff0c;如果还是采用传统线下的采购方式&#xff0c;那么很容易导致采购信息不集中&#xff0c;效率低&#xff0c;出错率高&#xff0c;最终损害企…

爱情呼叫转移-深度广度遍历合集

1.这件事是特殊的&#xff0c;还是普遍的&#xff1f; 工作中常常会遇到各种各样的问题&#xff0c;不管黑猫白猫&#xff0c;抓到老鼠就是好猫。哪只猫好&#xff0c;往往需要对比分析。 如何做数据对比&#xff0c;需要加入哪些数据来分析&#xff0c;在哪里进行数据对比&am…

查找 二分查找 (终极巩固)

二分条件&#xff1a; 1) 序列有序 2&#xff09;支持随机访问 二分思想&#xff1a; 大体思想是二分之后如果目标值在左侧&#xff0c;则中间包括右边区间所有pass掉 right mid - 1; 目标在右侧&#xff0c;则中间包括左边所有pass left mid 1; 注意点 left < rig…

Python Fiddler抓包工具教学,获取公众号(pc客户端)数据

前言 今天来教大家如何使用Fiddler抓包工具&#xff0c;获取公众号&#xff08;PC客户端&#xff09;的数据。 Fiddler是位于客户端和服务器端的HTTP代理&#xff0c;是目前最常用的http抓包工具之一。 开发环境 python 3.8 运行代码pycharm 2021.2 辅助敲代码requests 第三方…

VS2022 开发Qt之修改软件图标

开发环境本次实验使用的开发环境是win10 64位系统 IDE使用VS2022,Qt版本是Qt5,15.写博客背景最近再练习使用VS开发Qt,到修改软件图标的事情.在网上搜索了一番大部分修改图标的都是基于Qt自带的编译器,由于本人使用的VS的IDE和自带的编译器设置方法有所不同,在一番查找实验后还整…

【论文学习】YOLOv1-YOLOv4

文章目录You Only Look Once,Unified ,Real-Time Object DetectionAbstractIntroductionUnified DetectionNetwork DesignTrainingInferenceLimitations of YOLOComparison to Other Detection SystemsYOLO9000:Better,Faster,StrongerAbstractIntroductionBetterBatch Normali…

【C++之类和对象】日期类的实现

目录前言一、日期类的基本样式二、构造函数三、拷贝构造函数四、赋值运算符重载五、日期比较1. 判断一个日期是否小于另一个日期2. 判断一个日期和另一个日期是否相等3. 判断一个日期是否小于等于另一个日期4. 判断一个日期是否大于另一个日期5. 判断一个日期是否大于等于另一个…

独孤九剑xss通关教程

独孤九剑xss通关教程 独孤九剑第一式&#xff1a; 这里过滤了 () 构造payload&#xff1a; ?data"><svg><script>%26%23x65%3B%26%23x76%3B%26%23x61%3B%26%23x6c%3B%26%23x28%3B%26%23x6c%3B%26%23x6f%3B%26%23x63%3B%26%23x61%3B%26%23x74%3B%26%23…

开门红,农民大衣哥兔年第一条祝福,为何在百万艺人中选择杨语莲

俗话说&#xff1a;人逢喜事精神爽。这句话用到农民歌唱家大衣哥身上&#xff0c;就再贴切不过了&#xff0c;因为在新年即将来临之际&#xff0c;他的儿子小伟又一次结婚了。大衣哥是一个非常接地气的明星&#xff0c;这些年来他无绯闻不炒作&#xff0c;堪称为娱乐圈的楷模&a…

开学季,送初三学生什么礼物最实用?2023学生护眼台灯分享

春节的新学期即将到来&#xff0c;送给初中孩子什么礼物比较好呢&#xff0c;还是要对学习有所帮助的&#xff0c;还需要培养孩子的兴趣&#xff0c;在挑选礼物时&#xff0c;也是斟酌了很久&#xff0c;面对现在很多孩子的有近视问题&#xff0c;在我国的近视人数达到7亿人&am…

java面试题(十一)IO流篇

2.21 请介绍TreeMap的底层原理 参考答案 TreeMap基于红黑树&#xff08;Red-Black tree&#xff09;实现。映射根据其键的自然顺序进行排序&#xff0c;或者根据创建映射时提供的 Comparator 进行排序&#xff0c;具体取决于使用的构造方法。TreeMap的基本操作containsKey、g…