七大排序算法详解

1.概念

1.排序的稳定性

常见的稳定的排序有三种:直接插入排序,冒泡排序,归并排序

对于一组数据元素排列,使用某种排序算法对它进行排序,若相同数据之间的前后位置排序后和未排序之前是相同的,我们就成这种排序算法具有稳定性

单看单个属性的稳定性并无意义,稳定性主要体现在对具有多个属性的对象进行排序时才有意义
假设一个订单对象有两个属性,分别是下单时间与下单金额:
此时我们有一个需求,就是按照订单金额从高到低排序,若金额相同,则按照下单的先后时间排序

  • 方法一:就是先按照顺序排序,然后把金额相同的订单再次按照时间排序,但是这样就需要多次排序
  • 方法二:如果我们先把订单按照下单时间的先后排好序,然后再按照订单金额排序,此时如果我们使用的排序是稳定性的,那么它排序后同样是按照下单顺序先后排列的,此时我们就只需要两次排序

所以排序的稳定性也是非常重要的

2.排序分类

1.外部排序(不牵扯元素大小比较)

外部排序主要有,桶排序,计数排序,基数排序,时间复杂度近乎O(n)
这三种排序的集合元素非常大,内存放不下,需要使用外部存储器来存储排序,并且对数据的要求非常严格

2.内部排序(基于比较的方式)

在这里插入图片描述

1.插入排序

⭐直接插入排序(稳定)

1.核心思路

每次从无序区间中选择第一个元素,插入到有序区间的合适位置(相当于打扑克牌码牌的过程),有序区间+1,无序区间-1,直至整个数组有序
在这里插入图片描述
⭐⭐⭐直接插入排序在近乎有序的集合性能上非常好(是因为近乎有序的集合,不需要频繁的去交换),常常作为其他高阶排序的优化手段

2.详细代码
    /*** 直接插入排序* @param nums*/public static void insertSort(int[] nums) {// 有序区间[0,i)// 无序区间[i,n)for (int i = 1; i < nums.length; i++) {for (int j = i; j-1 >= 0; j--) {// 若当前值比前一个位置值还小,交换位置if (nums[j] < nums[j-1]) {swap(nums, j , j-1);}}}}

⭐希尔排序

希尔排序是对插入排序的优化,因为插入排序在近乎有序的数组上性能很好,希尔排序正是利用了这一点

1.核心思路

希尔排序不断地将原数组分为若干个子数组,先将子数组内部调整为有序,不断变大分组的长度,当分组长度为1时(一个元素天然有序),此时进行一次插入排序即可

在这里插入图片描述

2.详细代码
   // 希尔排序public static void shellSort(int[] arr) {int gap = arr.length >> 1;while (gap > 1) {// 先按照gap分组,组内使用插入排序insertionSortByGap(arr,gap);gap = gap >> 1;}// 当gap == 1时,整个数组接近于有序,此时来一个插入排序insertionSortByGap(arr,1);}// 按照gap分组,组内的插入排序private static void insertionSortByGap(int[] arr, int gap) {// i初始化为0也可以,更容易理解for (int i = gap; i < arr.length; i++) {for (int j = i; j - gap >= 0 && arr[j] < arr[j - gap] ; j -= gap) {swap(arr,j,j - gap);}}}

2.选择排序

⭐直接选择排序(不稳定)

1.核心思路

每次在无序区间选择最小值与无序区间第一个位置元素交换,有序区间+1,无序区间-1,直至整个数组有序
在这里插入图片描述

2.详细代码
    /*** 直接选择排序* @param nums*/public static void selectionSort(int[] nums) {// 起始状态:有序区间[0,i)// 无需区间[i,n)for (int i = 0; i < nums.length - 1; i++) {// 指向当前无需区间最小值的下标int minIndex = i;for (int j = i+1; j < nums.length; j++) {// 若当前值比最小值还小if (nums[j] < nums[minIndex]) {// 更新最小值下标minIndex = j;}}// 此时minIndex指向无需区间的最小值,将其加载有序区间的后面,有序区间+1,无序区间-1swap(nums, i, minIndex);}}

⭐堆排序

堆排详情博客:
原地堆排序

3.交换排序

⭐冒泡排序(稳定)

1.核心思路

每次遍历将无序数组的最大元素交换至末尾,无序数组-1,有序数组+1,直至整个数组有序

2.详细代码
    // 无序区间[0...i]// 有序区间[]public static void bubbleSort(int[] arr) {// 外层循环表示要进行元素操作的趟数for (int i = 0; i < arr.length - 1; i++) {boolean isSwaped = false;for (int j = 0; j < arr.length - i - 1; j++) {if (arr[j] > arr[j + 1]) {isSwaped = true;swap(arr,j,j + 1);}}if (!isSwaped) {break;}}}

⭐快速排序(不稳定)

1.核心思路

每次从无序数组中选取一个元素作为分区点(pivot),将原集合中所有<pivot的元素都放在分区点的左侧,将所有>pivot的元素都放在分区点的右侧,这样分区点最终位置就确定了,继续在左半区间和右半区间重复此过程即可
在这里插入图片描述

快速排序和直接选择排序不同的是在快排选择的过程中在不断地调整元素的顺序,在这个过程中原数组已经不断有序了

2.详细代码
    /*** 快速排序(挖坑法)*/public static void quitSort(int[] nums) {quitSortInternal(nums, 0, nums.length-1);}private static void quitSortInternal(int[] nums, int l, int r) {if (l >= r) {return;}// 分区之后,返回已经放好位置的元素下标int p = quitSortByHole(nums, l, r);// 将放好位置元素的左侧丢进去排序quitSortInternal(nums, l, p - 1);// 在将放好位置元素的右侧丢进去排序quitSortInternal(nums, p + 1, r);// 此时数组就整体有序了}/*** 使用非递归的方式* @param nums* @param l* @param r*/private static void quitSortInternal1(int[] nums, int l, int r) {Deque<Integer> stack = new ArrayDeque<>();stack.push(r);stack.push(l);while (!stack.isEmpty()) {// 获取左右区间int i = stack.pop();int j = stack.pop();if (i >= j) {continue;}// 调用获得一个位置的结果int p = quitSortByHole(nums, i, j);// 将左边压入栈中stack.push(p-1);stack.push(i);// 右边压入栈中stack.push(j);stack.push(p+1);}}private static int quitSortByHole(int[] nums, int l, int r) {// 分区数字int pivot = nums[l];int i = l;int j = r;while (i < j) {while (i < j && nums[j] >= pivot) {j--;}// 走到这说明nums[j] < pivotnums[i] = nums[j];while (i < j && nums[i] <= pivot) {i++;}// 走到这说明nums[i] > pivotnums[j] = nums[i];}// 出循环说明i==j// 将pivot写回inums[i] = pivot;// 返回分区点最终位置return i;}

4.归并排序

⭐归并排序(稳定,时间复杂度O(nlogn),空间复杂度O(n))

对原始数据不敏感

1.核心思路

1. 先不断地将原数组一分为二,直至子数组长度为1
2. 不断地将两个相邻的有序子数组合并成一个更大的有序子数组,直至合并后的数组与原数组长度相同,此时排序完成
在这里插入图片描述
核心操作:合并两个子数组merge(nums, l, mid, r)
int i=l代表左边数组走到的下标,
int j=mid+1代表右边数组走到的下标,
k代表当前原数组合并到哪个位置

2.归并排序应用

在这里插入图片描述

3.详细代码
    /*** 归并排序*/public static void mergeSort(int[] nums) {mergeSortInternal(nums, 0, nums.length-1);}/*** 在nums的l-r内进行归并排序* @param nums* @param l* @param r*/private static void mergeSortInternal(int[] nums, int l, int r) {if (l >= r) {return;}int mid = l + ((r - l) >> 1);;// 将左边和右边丢到mergemergeSortInternal(nums, l, mid);mergeSortInternal(nums, mid+1, r);// 此时说明左右两个数组都已经排好序merge(nums, l, mid, r);}private static void merge(int[] nums, int l, int mid, int r) {// 创建一个大小与r-l+1一样大的数组int[] aux = new int[r - l + 1];System.arraycopy(nums, l, aux, 0, r - l + 1);int i = l;int j = mid+1;// i代表左边数组走到的下标,j代表右边数组走到的下标,k代表当前原数组合并到哪个位置for (int k = l; k <= r; k++) {if (i > mid) {// 说明左边的数组已经走完,把右边的全部写回原数组即可nums[k] = aux[j-l];j++;} else if (j > r) {// 说明右边的数组已经走完,把左边的全部写回原数组即可nums[k] = aux[i-l];i++;} else if (aux[i-l] <= aux[j-l]) {// 说明左边的数字小,把左边数组内的数字写回原数组nums[k] = aux[i-l];i++;} else {// 说明右边的数字小,把右边数组内的数字写回原数组nums[k] = aux[j-l];j++;}}}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学建模(五)非线性规划

课程推荐&#xff1a; 13 非线性规划算法在数学建模中的应用与编程实现_哔哩哔哩_bilibili 一、非线性规划模型 如果目标函数或约束条件中包含非线性函数&#xff0c;就称这种规划问题为非线性规划问题。一般说来&#xff0c;解非线性规划要比解线性规划问题困难得多。而且&am…

cs231n assignment3 q4 Generative Adversarial Networks

文章目录 嫌墨迹直接看代码Q4 :Generative Adversarial Networkssample_noise题面解析代码输出 discriminator题面解析代码输出 generator题面解析代码输出 discriminator_loss题面解析代码输出 generator_loss题面解析代码 get_optimizer题面解析代码输出 ls_discriminator_lo…

c语言函数指针和指针函数的区别,以及回调函数的使用。

函数指针是什么&#xff0c;函数指针本质也是指针&#xff0c;不过是指向函数的指针&#xff0c;存储的是函数的地址。 指针函数是什么,指针函数其实就是返回值是指针的函数&#xff0c;本质是函数。 函数指针是如何定义的呢&#xff0c;如下 void (*pfun)(int a,int b) 这…

服务器的介绍

1.服务器概述 1.1 服务器的基本概念 服务器是计算机的一种&#xff0c;是网络中为客户端计算机提供各种服务的高性能计算机&#xff1b; 服务器在网络操作系统的控制下&#xff0c;将与其相连的硬盘、磁带、 打印机及昂贵的专用通讯设备提供给网络上的客户站点共享&#xf…

2023年国赛 高教社杯数学建模思路 - 案例:最短时间生产计划安排

文章目录 0 赛题思路1 模型描述2 实例2.1 问题描述2.2 数学模型2.2.1 模型流程2.2.2 符号约定2.2.3 求解模型 2.3 相关代码2.4 模型求解结果 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 最短时…

HTTP协议初识·上篇

目录 认识URL urlencode和urldecode 如何编码解码和验证过程 一个基本的网络服务器的流程 代码验证请求与响应 准备工作 HTTPServer.hpp Protocol.hpp makefile 1请求 HTTPServer.hpp 1.0函数handlerHttp-基本流程 再次处理 HttpServer.cc(新建文件) 测试1 -- 请…

iOS开发之查看静态库(.a/.framework)中包含的.o文件和函数符号(ar,nm命令)

.a/.framework其实是把编译生成的.o文件&#xff0c;打包成一个.a/.framework文件。a的意思是archive/归档的意思。 查看静态库.a文件包含的内容用下面的命令解压&#xff1a; ar x xxx.a 用ar命令打包静态库&#xff1a; 参数r是将后面的*.o或者*.a文件添加到目标文件中 参数…

031 - 浮点类型(近似值 FLOAT,DOUBLE)

-FLOAT&#xff0c;DOUBLE&#xff1a; FLOAT和DOUBLE类型代表近似数字数据值。MySQL将四个字节用于单精度值&#xff0c;并将八个字节用于双精度值。 对于FLOAT&#xff0c;SQL标准允许对FLOAT括号中的关键字后面的位以精度&#xff08;而不是指数的范围&#xff09;进行可选规…

全流程R语言Meta分析核心技术高阶应用

查看原文>>>全流程R语言Meta分析核心技术高阶应用 目录 专题一、Meta分析的选题与检索 专题二、Meta分析与R语言数据清洗及统计方法 专题三、R语言Meta分析与作图 专题四、R语言Meta回归分析 专题五、R语言Meta诊断分析 专题六、R语言Meta分析的不确定性 专题…

YoloV5环境搭建记录

https://github.com/ultralytics/yolov5/ 1、在Anaconda Promptx新建conda虚拟环境 conda create -n py39_yolov5 python3.9 2、激活虚拟环境 conda activate py39_yolov5 3、虚拟环境下装所需依赖 conda install pytorch1.12.1 torchvision0.13.1 torchaudio0.12.1 cpuo…

代码仓库设置访问权限

通过设置IP白名单的IP范围和访问控制&#xff0c;限制用户的访问和上传下载权限&#xff0c;大大增强仓库的安全性。 对于测试环境和生产环境都不应该增加“允许提交代码”权限 只有开发环境才允许

嵌入式Linux人脸检测libfacedetection

人脸检测 此库依赖Opencv&#xff0c;所以首先要移植Opencv到板子上。 笔者使用LVGL搭建了一个界面&#xff0c;界面有些卡顿&#xff08;主要原因是文件存取较慢&#xff09;&#xff0c;演示效果如下&#xff1a; OpenCV 首先要交叉编译Opencv 参考&#xff1a;https://…

一生一芯9——ubuntu22.04安装valgrind

这里安装的valgrind版本是3.19.0 下载安装包 在选定的目录下打开终端&#xff0c;输入以下指令 wget https://sourceware.org/pub/valgrind/valgrind-3.19.0.tar.bz2直至下载完成 解压安装包 输入下面指令解压安装包 tar -xvf valgrind-3.19.0.tar.bz2.tar.bz2注&#xf…

春秋云镜 CVE-2019-16113

春秋云镜 CVE-2019-16113 Bludit目录穿越漏洞 靶标介绍 在Bludit<3.9.2的版本中&#xff0c;攻击者可以通过定制uuid值将文件上传到指定的路径&#xff0c;然后通过bl-kernel/ajax/upload-images.php远程执行任意代码。 启动场景 漏洞利用 exp https://github.com/Kenun…

AWS 提示证书签名过期无法自动更新

如果域名没有通过验证的话&#xff0c;证书的过去是没有办法自动更新的。 验证的方式也非常简单&#xff0c;通过下面的配置&#xff0c;把 CNAME添加到你的域名上面&#xff0c;AWS 就可会自动完成验证了。 当添加完成后&#xff0c;AWS 验证需要的时间大致在 30 分钟到 1 个…

优美而高效:解决服务器通信问题

题目背景 在这个问题中&#xff0c;我们面临着一幅服务器分布图。图中的每个单元格可能有服务器&#xff08;标记为1&#xff09;或者没有&#xff08;标记为0&#xff09;。我们的任务是找出能够与至少一台其他服务器进行通信的服务器数量。 算法思路 为了解决这个问题&…

HTTP原理与实现

一、基本概念 一、基本原理* 1、全称&#xff1a; HyperText Transfer Protocol (超文本传输协议) 2、底层实现协议&#xff1a;建立在 TCP/IP 上的无状态连接。 3、基本作用&#xff1a;用于客户端与服务器之间的通信&#xff0c;规定客户端和服务器之间的通信格式。包括请…

婚恋交友h5多端小程序开源版开发

婚恋交友h5多端小程序开源版开发 以下是婚恋交友H5多端小程序的功能列表&#xff1a; 用户注册和登录&#xff1a;用户可以通过手机号码或第三方账号注册和登录。个人信息填写&#xff1a;用户可以填写个人基本信息&#xff0c;包括姓名、性别、年龄、身高、体重、学历、职业等…

Qt应用开发(拓展篇)——示波器/图表 QCustomPlot

一、介绍 QCustomPlot是一个用于绘图和数据可视化的Qt C小部件。它没有进一步的依赖关系&#xff0c;提供友好的文档帮助。这个绘图库专注于制作好看的&#xff0c;出版质量的2D绘图&#xff0c;图形和图表&#xff0c;以及为实时可视化应用程序提供高性能。 QCustomPl…

Docker-Consul

Docker-Consul 一、介绍1.什么是服务注册与发现2.什么是consul3.consul提供的一些关键特性&#xff1a; 二、consul 部署1.环境准备2.consul服务器3.查看集群信息4.通过 http api 获取集群信息 三、registrator服务器1.安装 Gliderlabs/Registrator2.测试服务发现功能是否正常3…