基本排序算法
目录
一,插入排序
二,希尔排序
三,选择排序
四,冒泡排序
五,快排
5.1 Hoare法
5.2 挖坑法
5.3 指针法
5.4 非递归写法
六,归并排序
6.1 递归
6.2 非递归
一,插入排序
基本思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

/*** 直接插入排序* 时间复杂度:O(n^2)* 空间复杂度:O(1)* 稳定性:稳定*/public void insertSort(int[] arr){for (int i = 1; i < arr.length; i++) {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;}}
二,希尔排序
基本思想:先选定一个整数,把待排序文件中所有记录分成多个组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后gap/=2,重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序。画个图理解一下:

/*** 希尔排序 - 直接排序的优化版* 时间复杂度:O(n^1.3)~O(1^1.5)* 空间复杂度:O(1)* 稳点性:不稳定*/public void shellSort(int[] arr){int gap = arr.length;while(gap > 1){gap /= 2;for (int i = gap; i < arr.length; i++) {int tmp = arr[i];int j = i - gap;for (; j >= 0; j -= gap) {if(arr[j] > tmp){arr[j+gap] = arr[j];}else{break;}}arr[j+gap] = tmp;}}}
三,选择排序
基本思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
/*** 选择排序* 时间复杂度:O(n^2)* 空间复杂度:O(1)* 稳定性:不稳定*/public void selectSort(int[] arr){for (int i = 0; i < arr.length; i++) {int minIndex = i;for (int j = i+1; j < arr.length; j++) {if(arr[minIndex] > arr[j]){minIndex = j;}}swap(arr,minIndex,i);}}public void swap(int[] arr, int i, int j){int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}
四,冒泡排序
基本思想:根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
/*** 冒泡排序* 时间复杂度:O(n^2)* 空间复杂度:O(1)* 稳定性:稳定*/public void bubbleSort(int[] arr){for (int i = 0; i < arr.length-1; i++) {boolean flg = true;for (int j = 0; j < arr.length-1-i; j++) {if(arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;flg = false;}}if(flg){break;}}}
五,快排
基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
5.1 Hoare法

从整体看,这就像一颗二叉树,所以我们可以用类似二叉树遍历的递归来实现,代码如下:
/*** 快排* 时间复杂度:O(nlogN)* 空间复杂度:O(logN)* 稳定性:不稳定*/ public void quickSort(int[] arr, int left, int right){if(left > right) return;//递归终止条件int div = partition(arr, left, right);//得到基准值下标quickSort(arr,left,div-1);//递归基准值前面的值quickSort(arr,div+1,right);//递归基准值后面的值}public int partition(int[] arr, int left, int right){int tmp = left;int key = arr[left];while(left < right){//注意这里只能先遍历右边,否则基准值的前面就会存在 >基准值的值,//后面就会存在 <基准值的值// && = 号必须有,不然如果基准和R相同,就会出现死循环while(left < right && arr[right] >= key){right--;}while(left < right && arr[left] <= key){left++;}swap(arr,left,right);}swap(arr,tmp,left);return left;//or right}
5.2 挖坑法
与Hoare法类似,只不过它把基准的初始位置当作一个坑,查找右边,将右边的值赋给坑,将右边变成坑,再查找左边,将左边的值赋给坑,将左边变成坑,重复以上操作直到 L== R,将arr[L] = key。再往下面递归,这里就不画图讲解了,直接上代码:
public int partition(int[] arr, int left, int right){int tmp = arr[left];while(left < right){while(left < right && arr[right] >= tmp){//=必须有 , 必须是right先走right--;}arr[left] = arr[right];while(left < right && arr[left] <= tmp){left++;}arr[right] = arr[left];}arr[left] = tmp;return left;}
5.3 指针法
它的主要思想没变,还是找到基准值的下标位置,将其分成两份,依次类推,但是它寻找基准的方法很神奇,先看代码:
public int partition(int[] arr, int left, int right){int prev = left;int cur = left + 1;while(cur <= right){if(arr[cur] < arr[left] && (++prev) != cur ){swap(arr,prev,cur);}cur++;}swap(arr,left,prev);return prev;}

5.4 非递归写法
public void quickSortNor(int[] arr, int left, int right){Stack<Integer> ret = new Stack<>();ret.push(left);ret.push(right);while(!ret.empty()){right = ret.pop();left = ret.pop();int div = partition(arr,left,right);//找到基准的下标if(left + 1 < div){//基准左边有2+的元素ret.push(left);ret.push(div-1);}if(right-1 > div){//基准右边有2+的元素ret.push(div+1);ret.push(right);}}}
六,归并排序
基本思路:将一组数据分成等长的两份,再将每份分成等长的两份,直到每份数据的长度都为一,然后再逆推回去,每次逆推都要进行一次排序,直到变成一份。如图:

6.1 递归
可以通过子问题的思路来理解代码:先将前面的一半排序,再将后面的一半排序,最后将整体排序,它们的每一部分都可是这样操作,所以可以使用递归解决。
/*** 归并排序* 时间复杂度:O(nlogn)* 空间复杂度:O(n)* 稳定*/public void mergeSort(int[] arr, int left, int right){if(left >= right) return;int mid = left + (right - left)/2;mergeSort(arr,left,mid);// 前 n/2 排序mergeSort(arr,mid+1,right);// 后 n/2 排序merge(arr,left,right,mid);// 整体排序}public void merge(int[] arr, int left, int right, int mid){int s1 = left;int s2 = mid+1;int k = 0;int[] tmp = new int[right-left+1];while(s1 <= mid && s2 <= right){if(arr[s1] <= arr[s2]){tmp[k++] = arr[s1++];}else{tmp[k++] = arr[s2++];}}while(s1 <= mid){tmp[k++] = arr[s1++];}while (s2 <= right){tmp[k++] = arr[s2++];}for (int i = 0; i < tmp.length; i++) {arr[i+left] = tmp[i];}}
6.2 非递归
思路:直接将其分成一个一组,然后再两两组合,直到合成一体,就只有上面那张图的下半部分:

public void mergeSortNor(int[] arr){int gap = 1;while(gap < arr.length){for (int i = 0; i < arr.length; i+=2*gap) {int left = i;//相邻两段子数组的开始和末位下标 [left,mid] [mid+1,right]int mid = left + gap -1;int right = mid + gap;if(mid >= arr.length){//说明只有前面一段数组mid = arr.length - 1;}if(right >= arr.length){//说明后面的子数组数量少right = arr.length-1;}merge(arr,left,right,mid);}gap *= 2;}}
相关文章:
基本排序算法
目录 一,插入排序 二,希尔排序 三,选择排序 四,冒泡排序 五,快排 5.1 Hoare法 5.2 挖坑法 5.3 指针法 5.4 非递归写法 六,归并排序 6.1 递归 6.2 非递归 一,插入排序 基本思想&…...
python调用百度ai将图片/pdf识别为表格excel
python调用百度ai将图片识别为表格excel 表格文字识别(异步接口)图片转excel 表格文字识别V2图片/pdf转excel通用 表格文字识别(异步接口) 图片转excel 百度ai官方文档:https://ai.baidu.com/ai-doc/OCR/Ik3h7y238 使用的是表格文字识别(异步接口),同步…...
Ansible最佳实践之Playbook管理滚动更新
写在前面 理解不足小伙伴帮忙指正 傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡…...
基于Citespace、vosviewer、R语言的文献计量学可视化分析及SCI论文高效写作方法教程
详情点击链接:基于Citespace、vosviewer、R语言的文献计量学可视化分析技术及全流程文献可视化SCI论文高效写作方法 前言 文献计量学是指用数学和统计学的方法,定量地分析一切知识载体的交叉科学。它是集数学、统计学、文献学为一体,注重量…...
【MATLAB】GM(1,1) 灰色预测模型及算法
一、灰色预测模型概念 灰色预测是一种对含有不确定因素的系统进行预测的方法。 灰色预测通过鉴别系统因素之间发展趋势的相异程度,即进行关联分析,并对原始数据进行生成处理来寻找系统变动的规律,生成有较强规律性的数据序列,然后…...
Go重写Redis中间件 - Go实现Redis协议解析器
Go实现Redis协议解析器 Redis网络协议详解 在解决完通信后,下一步就是搞清楚 Redis 的协议-RESP协议,其实就是一套类似JSON、Protocol Buffers的序列化协议,也就是我们的客户端和服务端通信的协议 RESP定义了5种格式 简单字符串(Simple String) : 服务器用来返回简单的结…...
海外抖音Tiktok强势来袭,有些人半年赚别人十倍工资
TikTok作为一款流行的短视频社交应用程序,确实在全球范围内取得了很大的成功。许多人通过在TikTok上分享有趣、创意或有吸引力的视频内容,获得了广泛的关注和认可。一些用户甚至能够通过TikTok赚取高额的收入,远远超过传统职业所能获得的工资…...
devDept Eyeshot 2024 预告-Update-Crack
即将发布的版本 开发商在一个动态的环境中运作,事情可能会发生变化。本页提供的信息旨在概述 devDept 软件产品的总体方向。它仅供参考,不应作为做出任何决定性的依据。devDept Eyeshot 2024软件产品描述的任何特性或功能的开发、发布和时间安排仍由 dev…...
教雅川学缠论05-线段
线段需要满足下面4个条件: 1.是由3条笔,或者3条以上组成,同笔一样,线段也是有方向的 2.如果线段起始于向上笔,则终止与向上笔(一定不会终止与向下笔) 3.如果线段起始于向下笔,则终止…...
SpringBoot 配置⽂件
1.配置文件作用 整个项⽬中所有重要的数据都是在配置⽂件中配置的,⽐如: 数据库的连接信息(包含⽤户名和密码的设置);项⽬的启动端⼝;第三⽅系统的调⽤秘钥等信息;⽤于发现和定位问题的普通⽇…...
基于Python的电影票房爬取与可视化系统的设计与实现
博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…...
Packet Tracer – 配置系统日志和 NTP
Packet Tracer – 配置系统日志和 NTP 目标 第 1 部分:配置系统日志服务 第 2 部分:生成日志记录事件 第 3 部分:手动设置交换机时钟 第 4 部分:配置 NTP 服务 第 5 部分:验证带时间戳的日志 拓扑图 场景 在本…...
TypeScript 联合类型,类型推断,类型断言
联合类型 取值可以为多种类型中的一个 function func(str: number | string):void{}类型断言 当变量需要调用某属性的时候,有不确定当前的类型是什么,可以使用类型断言; 类型断言的两种方式: 1,<类型> 变量名…...
到底叫 集合还是数组还是list还是列表?
1 总体上可以将数据结构分为数组和集合两种,而列表是一个泛指 数组:在Java中,数组是一种基本数据类型,可以用来存储同一类型的多个元素,数组的长度是固定的。例如:int[] arr new int[10];List:…...
LBERT论文详解
论文地址:https://arxiv.org/abs/2105.07148 代码地址:https://github.com/liuwei1206/LEBERT 模型创新 LEBRT采用句子中的词语对(论文中称为Char-Word Pair)的特征作为输入作者设计Lexicon adapter,在BERT的中间某一…...
C++终止cin输入while循环时多读取^Z或^D的问题
原代码: istream& operator>>(istream& is, map<string, int>&mm) {string ss"";int ii0;is >> ss>>ii;mm[ss]ii;return is; }int main() {map<string,int>msi;while(cin>>msi);return 0; } 问题&…...
c#[WebMethod]方法接收前端传入的JsonArray的方法
一、第一种方法:可以这样接收前端传入的jsonArray字符串到一个类的数组中,然后遍历该数组取值 这种方法需要创建PointConfig类 class PointConfig{public string ptcrossing { get; set; }public string ptcrossingId { get; set; }public string camId …...
WebService 报错 集锦
报错1:url错误 我的是调用的url的端口错误。调用esb的url的端口错了,导致报错。有的人是uri错了。例如: www.globalcoding.com:9001/SAP_saveProduct/1.0.0 写成了 www.globalcoding.com:9001/SAP_savePoduct/1.0.0 报错如下:…...
C++--菱形继承
1.什么是菱形继承 单继承:一个子类只有一个直接父类时称这个继承关系为单继承 多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承 菱形继承的问题:菱形继承有数据冗余和二义性的问题,数据冗余是由于创建多个相同类型的…...
Vue 3:玩一下web前端技术(二)
前言 本章内容为VUE目录结构解析与相关工程技术讨论。 上一篇文章地址: Vue 3:玩一下web前端技术(一)_Lion King的博客-CSDN博客 下一篇文章地址: Vue 3:玩一下web前端技术(三)…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法
使用 ROS1-Noetic 和 mavros v1.20.1, 携带经纬度海拔的话题主要有三个: /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码,来分析他们的发布过程。发现前两个话题都对应了同一…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...
