八大排序算法(冒泡排序、快速排序、堆排序.....)

news2024/11/25 20:49:28

每坚持一天,offer就会离我更近一步🌹

文章目录

    • 冒泡排序
    • 选择排序
    • 插入排序
    • 希尔排序
    • 快速排序
    • 计数排序
    • 堆排序
    • 归并排序

冒泡排序

算法描述:从第一个元素开始,两两比较,如果前者比后者大,那么就将两者进行交换,这样每经过一次排序,都能找到一个最大的元素并且把它放在数组的最后。
稳定性:稳定
时间复杂度:O(N^2)
代码:

public static int[] bubbleSort(int[] arr){

        for (int i = 0; i < arr.length - 1; i++) {
//            比较次数要减去i,每比较一次都会把最大的排到最后
            for (int j = 0; j < arr.length - 1 - i; j++) {
//                如果前边元素比后边的元素大就交换
                if(arr[j+1] < arr[j]){
                    int temp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
        return arr;
    }

选择排序

算法描述:在每一次排序时,先假设第一个元素是最小的,然后从第二个元素一直遍历到最后一个元素,如果找到比第一个小的元素就进行交换,否则不交换。第一次排序时,有序区间中只有一个元素;第二次排序,有序区间中有两个元素,依次递增,直到所有元素都有序
时间复杂度:O(N^2)
稳定性:不稳定
代码:

public static void selectSort(int[] arr){
        for(int i = 0;i < arr.length - 1;i++){
//            假设第一个元素是最小的
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
//                再从无序的元素中找到比arr[minIndex]小的元素,进行交换
                if (arr[j]<arr[minIndex]){
                    int temp = arr[j];
                    arr[j] = arr[minIndex];
                    arr[minIndex] = temp;
                }
            }
        }

    }

插入排序

算法描述:,初始时,先把第一个元素看成是有序的,然后把未排序的元素一个一个插入到有序序列中。
时间复杂度:O(N^2)
稳定性:稳定

public static void insertSort(int[] arr){
//        将arr[0]看作是有序的,所以从arr[1]开始遍历
        for (int i = 1; i < arr.length; i++){
//        暂存待插入元素
            int inserted = arr[i];

            int j = i - 1;
//            从后往前开始比较,如果待插入元素更小就将有序元素后移
            for (; j >= 0 && inserted < arr[j]; j--) {
                arr[j+1] = arr[j];
            }
//        将待插入元素插入
            arr[j+1] = inserted;
        }
    }

希尔排序

改进了插入排序

public static void shellSort(int[] arr){
        int n = arr.length;
        for(int gap = n/2;gap > 0; gap /= 2){
            for (int i = gap; i < n; i++) {
                int inserted = arr[i];
                int j=i-gap;
                for (; j >= 0&&arr[j]>inserted; j-=gap) {
                    arr[j+gap] = arr[j];
                }
                arr[j+gap] = inserted;
            }
        }

    }

快速排序

算法描述:选择第一个元素当哨兵,一个左指针一个右指针,左指针从左开始扫描,遇到比哨兵大的元素就停;右指针从右开始扫描,遇到比哨兵小的元素就停,然后交换两个元素,直到左指针和右指针相遇,并交换相遇处的元素和哨兵。然后分别进行左半部分和右半部分的排序,同样的过程。
时间复杂度:O(NlogN)
稳定性:不稳定
代码:

public static void quickSort(int[] arr,int begin,int end){
        if (begin > end) return;
//        第一个元素当作哨兵
        int pivot = arr[begin];

        int i = begin;
        int j = end;
        while (true){
//            从后往前找比哨兵小的
            while (arr[j] >= pivot && i < j)
                j--;
//            从前往后找比哨兵大的
            while (arr[i] <= pivot && i < j)
                i++;
//            两个指针相遇就暂停
            if (i >= j){
                break;
            }
//            指针相遇后交换元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
//          交换哨兵和指针相遇处的元素
        arr[begin] = arr[i];
        arr[i] = pivot;
//        对左半部分元素进行排序
        quickSort(arr,begin,i-1);
//        对右半部分元素进行排序
        quickSort(arr,i+1,end);
    }

计数排序

算法描述:从初始数组中选取一个最大的元素,用它来做辅助数组的长度,然后遍历初始数组,统计每一个元素出现的次数并保存到辅助数组中,然后遍历辅助数组,取出元素并覆盖初始数组即可。
时间复杂度:O(N)
空间复杂度:O(N)
适用于元素范围较小的数组
代码:

public static void countSort(int[] arr){
        int max = Integer.MIN_VALUE;
//        找出数组中最大的数
        for(int num:arr){
            if(num > max) max = num;
        }
//      初始化计数数组,统计每个元素所出现的次数
        int[] temp = new int[max+1];
        for(int i=0;i<arr.length;i++){
            temp[arr[i]]++;
        }
//      取出计数数组中的元素,覆盖原来的数组
        int k = 0;
        for(int i=0;i<temp.length;i++){
            for(int j = temp[i];j > 0;j--){
                arr[k++] = i;
            }
        }
    }

堆排序

算法描述:先根据给定数组建一个大根堆(小根堆也可以),然后每次取堆顶元素和堆尾元素进行交换,此时取下来的堆顶元素就是当前数组中最大的,然后再次维护堆的性质,执行n次之后数组即为有序。
时间复杂度:O(NlogN)(建堆的时间复杂度是O(N),维护堆性质的时间复杂度是O(logN)
稳定性:不稳定
代码:

//    堆排序入口
    public static void heapSort(int[]arr){
        int n = arr.length;

        //建立堆,大根堆
        //        注意,建完堆之后是局部有序的,建堆的复杂度是O(n)
//        从n/2-1开始的原因:下标为i的节点的父节点下标是(i-1)/2,当i=n-1时,代入得i=n/2-1
        for( int i = n/2-1;i>=0;i--){
            heapify(arr,n,i);
        }

        //        排序
        //每次取堆中最大元素并维护堆的性质
        for( int i=n-1;i>0;i--){
            int temp = arr[i];
            arr[i] = arr[0];
            arr[0] = temp;
            heapify(arr,i,0);
        }
    }
//        比较的具体过程
    public static void heapify(int[] arr,int n,int i){
//        父节点下标
        int largest = i;
//        左孩子下标
        int lson = 2 * i + 1;
//        右孩子下标
        int rson = 2 * i + 2;
//        比较父节点和左孩子,左孩子下标必须小于n,如果左孩子大,则替换父节点
        if(lson<n&&arr[largest]<arr[lson]){
            largest = lson;
        }
//        比较父节点和右孩子,右孩子下标必须小于n,如果右孩子大,则替换父节点
        if(rson<n&&arr[largest]<arr[rson]){
            largest = rson;
        }
//        如果不满足大根堆的性质,则进行交换
//        将父节点和左右孩子中较大的元素交换
        if(largest!=i){
            int temp = arr[largest];
            arr[largest] = arr[i];
            arr[i] = temp;
//            向下继续比较
            heapify(arr,n,largest);
        }
    }

归并排序

算法描述:采用递归与分治的思想,先把数组按照两两划分的原则对数组分割,直到每个分组都是一个元素,然后再按照之前分割的顺序比较大小之后进行两两合并。
时间复杂度:O(NlogN)
稳定性:稳定
代码:

public static void merge(int[] arr,int[] tempArr,int left,int mid,int right){
//        标记左半区第一个未排序的元素
        int l_pos = left;
//        标记右半区第一个未排序的元素
        int r_pos = mid + 1;
//        临时数组元素的下标
        int pos = left;
//        开始合并
        while (l_pos <= mid&&r_pos <= right){
            if(arr[l_pos] < arr[r_pos])
                tempArr[pos++] = arr[l_pos++];
            else
                tempArr[pos++] = arr[r_pos++];
        }
//        可能左半区还有剩余元素
        while (l_pos <= mid)
            tempArr[pos++] = arr[l_pos++];
//        可能右半区还有剩余元素
        while (r_pos <= right)
            tempArr[pos++] = arr[r_pos++];
//        把临时数组的元素复制回主数组
        while (left <= right){
            arr[left] = tempArr[left];
            left++;
        }

    }


    public static void msort(int[] arr,int[] tempArr,int left,int right){
//        如果只有一个元素则不进行划分
        if(left < right){
            int mid = (left+right)/2;
            //递归划分左半部分
            msort(arr,tempArr,left,mid);
            //递归划分右半部分
            msort(arr,tempArr,mid+1,right);
            //合并
            merge(arr,tempArr,left,mid,right);
        }
    }

    public static void mergeSort(int[] arr){
        int n = arr.length;
//        分配一个辅助数组
        int[] tempArr = new int[n];
//        开始归并排序,传入左边界和右边界
        msort(arr,tempArr,0,n-1);
    }

在这里插入图片描述
整理也挺费时间的,如果觉得对你有帮助,点个赞再走吧!感谢收看!

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

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

相关文章

[oeasy]python0133_[趣味拓展]颜文字_流石兄弟_表情文字_2ch_kaomoji

颜文字 回忆上次内容 上次我们了解unicode 里面有各种字体 甚至还有emoji emoji 本质上也是文字 按照unicode的方式编码存储时按照utf-8的方式编码显示时按照系统定义的方式进行显示 还有什么好玩的亚文化吗&#xff1f;&#x1f914; emoticon 1982 年 9 月 19 日 诞生了第…

docker安装rabbitmq的延迟队列插件

1.进入rabbitmq镜像 docker exec -it rabbitmq bash2.查看rabbitmq版本号&#xff0c;方便查找对应版本的延迟队列插件 rabbitmqctl version2.查询rabbitmq插件列表 rabbitmq-plugins list若没有rabbitmq_delayed_message_exchange-xxx.ez&#xff0c;则可以去[延迟队列插件…

win11家庭版 使用vm进行虚拟化的设置(此平台不支持虚拟化的 Intel VT-x/EPT。)

一、安装vm,进入BIOS设置虚拟化&#xff08;vm安装16.2以上版本&#xff09; 这个网上很多&#xff0c;就不说了 二、此时安装vm,创建虚拟机就没问题了&#xff0c;但是想继续再虚拟化&#xff0c;将会有一个问题“此平台不支持虚拟化的 Intel VT-x/EPT。” &#xff08;很多…

中移链系统合约管控功能介绍

中移链是在满足我国信息化监管需求、合规可控的前提下&#xff0c;打造的中国移动区块链服务平台。如果把中移链类比为计算机系统&#xff0c;那么系统合约就是中移链中的系统设置部分&#xff0c;用于配置和管理链的资源和行为。在计算机系统中,系统设置提供了对计算机系统的底…

SE11/SM30 维护视图

文章目录创建维护视图偶遇错误创建维护视图 首先我们现在SE11中创建一个透明表,然后点击如下图 需要我们创建一个函数组,他的目的是为了让系统生成相应的代码放在这个函数组中,也可以说是SM30的操作界面;点击上面的保存就可以了 注意在输入屏幕编号的时候切记不要和其他的维护…

ChatGPT背后的逻辑

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl OpenAI与ChatGPT OpenAI是一个美国的人工智能&#xff08;AI&#xff09;研究实验室&#xff0c;由非营利组织OpenAI Incorporated和其盈利子公司OpenAI Limited Partnersh…

HTTPS 加密简析

1 前言 HTTPS采用的是对称加密和非对称加密的混合加密方法。 密码学知识可以查看我的这篇博客 CISSP考试要求里的“应用密码学”内容辅助记忆趣味串讲_晓翔仔的博客-CSDN博客 2.HTTPS加密过程 https在建立链接时是非对称加密&#xff0c;建立链接后是对称加密。 步骤1 客户端…

初识掌控板2.0、官方拓展板和配套编程软件mpython

不是广告&#xff01;&#xff01;不是广告&#xff01;&#xff01; 一、掌控板2.0概览 掌控板又名掌上联网计算机&#xff0c;是一款为青少年学习Python编程和创意制造&#xff0c;特别是物联网应用而设计的开源硬件。内置microPython开源嵌入式Python运行环境&#xff0c;可…

怎么将静图变动图?用这个网站就够了

在使用聊天工具聊天时&#xff0c;大家都喜欢用一些动态的表情包&#xff0c;这种动态表情包就是gif格式图片。因为其生动丰富的画面能够通过一张图片表达多种信息。那么&#xff0c;如何生成gif图片呢&#xff1f;一、什么工具能够制作gif动画&#xff1f; GIF中文网作为一款…

allwinner boot0启动

目录 路径&#xff1a;u-boot-2018/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds 路径&#xff1a;u-boot-2018/arch/arm/cpu/armv7/start.S 路径&#xff1a;u-boot-2018/arch/arm/lib/crt0.S 路径&#xff1a;u-boot-2014.07\common\board_f.c 路径&#xff1a;u-boot-2014.…

领英如何不让对方查看自己的好友,防止他人添加自己客户

那如何防止好友加自己的好友呢&#xff1f;其实领英是可以设置谁能查看到自己好友的&#xff0c;甚至不让所有人查看。 领英是一个关系性的职业社交平台&#xff0c;最大的特点就是关系性。彼此有某种关系的人或在3度内的人都可以查看对方的详细资料&#xff0c;甚至可添加对方…

Redis 如何配置读写分离架构(主从复制)?

文章目录Redis 如何配置读写分离架构&#xff08;主从复制&#xff09;&#xff1f;什么是 Redis 主从复制&#xff1f;如何配置主从复制架构&#xff1f;配置环境安装 Redis 步骤通过命令行配置从节点通过配置文件配置从节点Redis 主从复制优点Redis 主从复制缺点Redis 如何配…

第十四届蓝桥杯单片机省赛真题(巨简代码+超级详解)

文章目录前言一、陷阱分析二、代码相关定义、声明1.变量声明2.函数声明三、主要函数1.函数初始化 &#xff1a;关闭蜂鸣器、定时器初始化、设置时间、消除85℃影响、开启总中断2.按键扫描&#xff1a;长按松开清除数据&#xff0c;短按切换界面&#xff0c;加减参数3.数据采集与…

视频提取gif如何操作?教你用gif制作工具快速截取gif

从视频中提取gif动画就是将电影、电视剧中的某一段视频提取出来做成gif格式的动态图片。那么&#xff0c;如何使用电脑或是手机来将视频转换成gif动图呢&#xff1f; 一、使用什么工具能够完成视频转gif制作呢&#xff1f; 通过使用GIF中文网的视频转gif&#xff08;https://…

S型加减速速度给定功能块(SCL+梯形图)

S型加减速详细算法公式请参看下面博客文章,这里不再赘述: 博途PLC1200/1500PLC S型速度曲线变频器控制应用(SCL完整源代码)_RXXW_Dor的博客-CSDN博客PLC运动控制基础系列之梯形速度曲线,可以参看下面这篇博客:PLC运动控制基础系列之梯形速度曲线_RXXW_Dor的博客-CSDN博客运…

前段开发:配置VSCode像IDEA一样调试VUE项目

如果不配置VSCode调试&#xff0c;那么我们的前段项目一般都是在浏览器中的开发者工具中调试&#xff0c;这样对于使用习惯了IDEA开发调试的人特别不习惯&#xff0c;这几天个人研究了下VSCode中的代码调试功能&#xff0c;做以下记录&#xff1a; 1、使用插件调试&#xff1a…

应用DAP-seq技术鉴定百脉根中一个NAC转录因子在全基因上的靶基因,揭示硝酸盐诱导根瘤衰老的新机制

豆科植物通过与根瘤菌共生&#xff0c;形成能够固氮的根瘤。硝酸盐能够影响根瘤共生的过程&#xff0c;适宜浓度的硝酸盐促进结瘤固氮&#xff0c;而高浓度的硝酸盐抑制菌根共生&#xff0c;并且会促进根瘤衰老。NLP (NIN-Like Protein)转录因子调控硝酸盐信号转导&#xff0c;…

CSS实现三角形的四种方法

方法一&#xff1a;使用 border (常见) 【解释】不设置宽高&#xff0c;用边框大小控制三角型大小 【分解步骤】 设置一个div不设宽高 【示例】 <style>#triangle{width: 0;height: 0;border: 100px solid;border-color: orangered skyblue gold yellowgreen;} </s…

3.8——友元

类的主要特点之一是信息隐藏和封装&#xff0c;即类的私有成员和保护成员只能在定义的范围内使用&#xff0c;也就是说私有成员和保护成员只能通过类的成员函数来访问。但是&#xff0c;有时候我们在类外也需要访问私有成员数据或保护成员数据怎么办。这时我们就要通过友元函数…

gru 串联LLm

单纯是为了降低大LLM 设计的结构 当前如果transformers 可以 输出一个状态也是可以的 这样串联的好处是每次运行知识一个小模型的计算量 时间换空间的概念 可以训练100个模型而后根据需要进行微调 从100 个中选择一个预测比较接近的进行微调预测 预测后继续进行从100中选择 而后…