基础排序算法
插入排序(insertion sort)
插入排序每次循环将一个元素放置在适当的位置。像抓牌一样。手里的排是有序的,新拿一张牌,与手里的牌进行比较将其放在合适的位置。
插入排序要将待排序的数据分成两部分,一部分有序,另一部分待排序。默认任务数组第一个元素是有序的,然后依次取剩下的元素插入有序部分合适的位置。
算法实现
public static void sort(int[] arr){int len = arr.length;/*** 将数组分成两部分* [0] 已排序 & [1,2,3...length-1] 待排序* 第一层循环将待排序元素逐个拿出与已排序部分进行插入排序*/for (int i = 1; i < len; i++) {//先把当前循环要排序的元素从数组拿出来,空出来一个数组位置int val = arr[i];// j 当前插入位置指针int j = i-1;for (; j > 0 ; j--) {if(val < arr[j]){//当前插入指针位置元素比当前待排序值大,将当前位置元素后移arr[j+1] = arr[j];}else {//当前插入指针位置元素比当前值小,好了,就应该在这里插入,插入到指针位置的后面 j+1break;}}arr[j+1] = val; }}
实际数据分析:
例 {2,6,5,4,8,7}
排序过程: 默认数组第一个位置2已排好,从6开始插入排序。
第一次:把6拿出来,然后6的位置可以被覆盖。
内循环:插入指针为6的下标往前一个,第一次拿出2进行比较。6 >2 。6要插入2的后面,跳出循环
第二次:拿出5 内循环:插入指针为5的下标-1, 第一次拿出6,5<6。不能在这里插入,插入点还得往前移动。这个时候要把6的位置后移一位, 因为5要插入6前面,但是现在没有位置。正好5被拿出来了,5的位置现在可以被使用。 经过一次内循环插入指针移动到了2位置,6向后移动一位。这时数组变成{2,6,6,4,8,7}。内循环第二次拿出2,5>2, ok找到插入点了,跳出内循环,5插入2的后面也就是原来6的位置。 将5放入插入位置,这时候数组变成了{2,5,6,4,8,7}。结束5的排序
第三次依次操作。
插入排序的插入理解就是将待排序的当前元素插入到有序部分合适的位置。比较前先将当前元素拿出来,在比较的过程中,如果当前元素的排序位置没找到,不需要进行交换。只需要将当前有序部分的比较元素后移一位,让出插入位置。进行下一次比较依次类推。直到找到插入位置,将当前元素放入该位置。
插入排序最好情况时间复杂度是O(n)。已经是有序的了,只一遍外循环即可。最坏情况是O(n^2)。排序算法是稳定的,因为不存在交换。也不需要开辟额外的空间。
希尔排序
希尔排序是插入排序的变种。我们知道插入排序的时间复杂度是O(n^2)。一次只能对一个元素位进行排序,并且遇到较小值在数组后部时,要进行多次比较移位才能将其放置合适位置。希尔排序能提高一定的平均排序效率。但是实际中使用的可能也不太多。
排序原理
每次按特定步长(step)将待排序分成若干组,然后每组内进行插入排序。步长取值通常为元素长度 length/2,length/(2*2)…1。最后一次步长变成1演变成完全插入排序。
代码实现
static void sort(int[] arr){int len = arr.length;//step为步长,分组元素间的间隔for (int step = len/2; step >0; step /=2) {//每一组进行插入排序,for (int i = step; i < len; i++) {//外层循环每+1表示新一组元素int temp = arr[i];//待插入元素先拿出来int p = i;//当前插入指针,p-step是当前组已排序好的部分,依次拿出与当前值进行比较for (; p >= step ; p -= step) {//每次取同组元素,同组元素的间隔是step值if(arr[p - step] > temp){arr[p] = arr[p - step];}else{//找到插入位置break;}}arr[p] = temp;//将元素插入当前位置}}}
实例分析:
冒泡排序(Bubble sort)
排序算法像冒泡一样每次遍历通过比较找到待排序元素中最大的一个,然后上浮到已排序部分。
代码实现
static void sort(int[] arr){int len = arr.length;for (int i = 0; i < len-1; i++) {//len-i个元素已排好,所以内循环次数是len-i-1for (int j = 0; j < len-i-1; j++) {/**前面元素比后面元素大就进行交换,大元素后移。这样内循环结束后就找到了本次所有参与循环元素的最大值,并放到最后。*/if(arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;}}System.out.println(Arrays.toString(arr));;}}
优化:每次冒泡排序内循环记录是否有交换发生。如果没有交换发生,则整个数组已经是有序的了。仔细理解下这句话。代码实现
static void sort(int[] arr){int len = arr.length;for (int i = 0; i < len-1; i++) {boolean swap = false;for (int j = 0; j < len-i-1; j++) {if(arr[j] > arr[j+1]){int tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;swap = true;}}if(!swap) break;//没有交换发生,跳出循环System.out.println(Arrays.toString(arr));;}}
冒泡排序时间复杂度和插入排序一样最好都是O(n),最后是O(n^2)。
选择排序
排序思想
每次从未排序的部分选择最小(或最大)的元素,放到已排序部分的末尾,直到整个数组排序完成。
代码实现
public static void sort(int[] arr){int len = arr.length;for (int i = 0; i < len-1; i++) {int p = i;//记录最小位置指针,默认记录为本次循环第一个元素位置for (int j = i+1; j < len ; j++) {//如果当前数比原来标记最小数小,记录当前位置为最小数指针if( arr[j] < arr[p] ) p = j;}//找到本次最小数指针,如果指针不是第一个元素,将第一个元素与最小值元素进行位置交换if(p != i){int temp = arr[i];arr[i] = arr[p];arr[p] = temp;}}}
选择排序存在元素跨距离交换,不稳定,时间复杂度O(n^2)。理解起来和冒泡排序很像。不过中间少了很多交换。
归并排序
归并排序将待排序数组每次进行二分,直到每一组分成1个元素,则顺序也就出来了。然后再依次进行合并操作最后生成一个有序的操作。
分比较好操作每次数组进行二分即可。合就是要将分的两部分A、B依次拿出一个值(两部分当前最小的值,中间需要比较是取A部分的还是取B部分)来组合起来。因为分后的两部分已经是有序的了,所以最后两部分所有元素取完合起来的整个也是有序的。
排序过程图:
代码实现:
public static void sort(int[] arr,int start,int end){//元素开始和结束位置相等,不能再分了,结束if(start >= end) return;//将要排序的数组进行平分int mid = (start + end) /2;sort(arr,start,mid);//前半部分进行排序sort(arr,mid+1,end);//后半部分进行排序//合并本次排序结果merge(arr,start,mid,end);}/*** 排序两部分 {start,mid} ,{mid+1,end} 都已排序完成,合并两部分* 合并过程:*/public static void merge(int[] arr,int start,int mid,int end){int p1 = start;//左半部分当前下标int p2 = mid+1;//右半部分当前下标int index = start;//temp临时数组存储下标,从start开始/*** 合并已排序的两部分* 每次从左边部分和右边部分各拿出一个元素进行比较,小的放入数组中,* 然后从小的所在部分再拿出一个与上一次大的元素进行比较*/while (p1 <= mid && p2 <= end){if(arr[p1] < arr[p2]){temp[index++] = arr[p1++];}else{temp[index++] = arr[p2++];}}/*** while 循环结束表示至少数组两部分有一部分取完,但是不一定两部分都取完。* 最后将左边部分和右边部分可能剩余的部分放入临时数组中。*/while (p1 <= mid){temp[index++] = arr[p1++];}while (p2 <= end){temp[index++] = arr[p2++];}/*** 执行到这里 temp{start,end} 部分都已排好序,* 将temp{start,end}部分放入原数组中。*/for (int i = start; i <= end; i++) {arr[i] = temp[i];}}
快速排序
算法思想:
快速排序取数组第一个元素作为基准数,然后将剩余元素与基准数进行比较,比基准数大的放在基准数左边,小的放在基准数右边,基准数在中间。然后再将基准数两个子结果进行递归按上面取基准数排序。最后整个数组变为有序的。
代码实现
public static void sort(int arr[],int left ,int right){if(left >= right) return;int p1 = left;int p2 = right;int val = arr[left];//取数组第一个元素作为基准数while ( p1 < p2){/*** 从右往左找比基准数小的数* 找到后将其放到p1指针位置*/while (p2 > p1 && arr[p2] >= val)p2--;arr[p1] = arr[p2];/*** 从左往左找找到比基准数大的数* 找到后将其放到p2指针位置,这个时候p2经过上面的查找已经被放到p1位置,可以覆盖*/while (p1 < p2 && arr[p1] <= val)p1++;arr[p2] = arr[p1];//继续交叉查找}//找到中间位置了(左边的数都小于基准数,右边的数都大于基准数),将基准数放到该位置arr[p2] = val;//递归的将数组以基准数为分界点分成两部分,各自进行快速排序sort(arr,left,p2);sort(arr,p2+1,right);}
排序过程分析
首先取数组的第一个元素作为基准数,然后这样数组第一个位置就可以覆盖,然后从数组的末尾往前找比基准数小的数,如果找到就将其移动到原基准数的位置。这个时候刚被移动的元素位置又空出来了,这个时候在从前往后找比基准数大的,找到后在将其放到该位置。循环往复的进行以上操作。直到从后往前找的指针和从前往后找的指针位置相等,表示整个数组已经找完,将基准数放置在该位置。最后数组被分成了:[{小于基准数}{基准数}{大于基准数}]三部分。然后再对小于基准数部分和大于基准数部分进行递归的上面排序过程。直到被分元素只有一个,排序完成。
从上面的分析过程可以看出,快速排序会进行大量的跨距离移位操作,是不稳定的。平均时间复杂度是O(n*logn)
总结
排序算法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
冒泡排序 | 最好情况:O(n) 最坏情况:O(n^2) 平均情况:O(n^2) | O(1) | 小型数据集或部分有序数据集 |
插入排序 | 最好情况:O(n) ; 最坏情况:O(n^2) ; 平均情况:O(n^2) | O(1) | 小型数据集或部分有序数据集 |
选择排序 | 始终为O(n^2) | O(1) | 小型数据集 |
快速排序 | 最好情况:O(nlogn) ; 最坏情况:O(n^2) ;平均情况:O(nlogn) | 最好情况:O(logn) , 最坏情况:O(n) | 大型数据集,尤其是无序数据集 |
归并排序 | O(nlogn) | O(n) | 大型数据集,尤其是链表结构 |
如果对排序稳定性有要求,可以选择插入排序、归并排序。如果数据集较小且无序,可以选择冒泡排序、插入排序或选择排序。对于大型数据集,快速排序、归并排序通常效果更好。
相关文章:

基础排序算法
插入排序(insertion sort) 插入排序每次循环将一个元素放置在适当的位置。像抓牌一样。手里的排是有序的,新拿一张牌,与手里的牌进行比较将其放在合适的位置。 插入排序要将待排序的数据分成两部分,一部分有序&#…...

Nginx的反向代理、动静分离、负载均衡
反向代理 反向代理是一种常见的网络技术,它可以将客户端的请求转发到服务器群集中的一个或多个后端服务器上进行处理,并将响应结果返回给客户端。反向代理技术通常用于提高网站的可伸缩性和可用性,并且可以隐藏真实的后端服务器地址。 #user…...

LLM-TAP随笔——大语言模型基础【深度学习】【PyTorch】【LLM】
文章目录 2.大语言模型基础2.1、编码器和解码器架构2.2、注意力机制2.2.1、注意力机制(Attention)2.2.2、自注意力机制(Self-attention)2.2.3、多头自注意力(Multi-headed Self-attention) 2.3、transforme…...

蓝桥杯备赛-上学迟到
上学迟到 P5707 【深基2.例12】上学迟到 - 洛谷 |https://www.luogu.com.cn/problem/P5707 题目介绍 题目描述 学校和 yyy 的家之间的距离为 s 米,而 yyy 以v 米每分钟的速度匀速走向学校。 在上学的路上,yyy 还要额外花费 1010 分钟的时间进行垃圾分…...

基于 MATLAB 的电力系统动态分析研究【IEEE9、IEEE68系节点】
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
2023百度之星 题目详解 公园+糖果促销
2023百度之星题目详解 文章目录 2023百度之星题目详解前言公园问题题目详解 夏日漫步问题问题详情题目详解 前言 这里为大家带来最新的2023百度之星的题目详解,后续还会继续更新,喜欢的小伙伴可以点个关注啦! 公园问题 今天是六一节&#…...
C++ 2019-2022 CSP_J 复赛试题横向维度分析(中)
上文讲解了2019~2022年第一题和第二题。第一题偏数学认知,算法较简单,第二题考查基本数据结构,如队列、栈……和基础算法,如排序、模拟……。 本文继续讲解第三题和第四题。 1. 第三题 1.1 2022 题目: 逻辑表达式…...

基于Spring Boot的IT技术交流和分享平台的设计与实现
目录 前言 一、技术栈 二、系统功能介绍 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 我国科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域&#x…...
智算引领·创新未来 | 2023紫光展锐泛物联网终端生态论坛成功举办
9月21日,紫光展锐在深圳成功举办2023泛物联网终端生态论坛。论坛以“智算引领创新未来”为主题,吸引了来自信通院、中国联通、中国移动、中国电信、金融机构、终端厂商、模组厂商等行业各领域三百多位精英翘楚汇聚一堂,探讨在连接、算力驱动下…...
网络安全技术指南 103.91.209.X
网络安全技术指的是一系列防范网络攻击、保护网络安全的技术手段和措施,旨在保护网络的机密性、完整性和可用性。常见的网络安全技术包括: 防火墙:用于监控网络流量,过滤掉可能包括恶意软件的数据包。 加密技术:用于保…...

用flex实现grid布局
1. css代码 .flexColumn(columns, gutterSize) {display: flex;flex-flow: row wrap;margin: calc(gutterSize / -2);> div {flex: 0 0 calc(100% / columns);padding: calc(gutterSize / 2);box-sizing: border-box;} }2.用法 .grid-show-item3 {width: 100%;display: fl…...

东郊到家app小程序公众号软件开发预约同城服务系统成品源码部署
东郊到家app系统开发,东郊到家软件定制开发,东郊到家小程序APP开发,东郊到家源码定制开发,东郊到家模式系统定制开发 一、上门软件介绍 1、上门app是一家以推拿为主项,个人定制型的o2o平台,上门app平台提…...

kotlin的集合使用maxBy函数报NoSuchElementException
kotlin设定函数 fun test() {listOf<Int>().maxBy { it } } 查看java实现...

Python开发与应用实验2 | Python基础语法应用
*本文是博主对学校专业课Python各种实验的再整理与详解,除了代码部分和解析部分,一些题目还增加了拓展部分(⭐)。拓展部分不是实验报告中原有的内容,而是博主本人自己的补充,以方便大家额外学习、参考。 &a…...

网络安全--防火墙旁挂部署方式和高可靠性技术
目录 一、防火墙 二、防火墙旁挂部署方式 使用策略路由实现 第一步、IP地址配置 第二步、配置路由 第三步、在防火墙上做策略 第四步、在R2上使用策略路由引流 三、防火墙高可靠性技术--HRP 拓扑图 第一步、配置SW1、SW2、FW1、FW2 第二步、进入防火墙Web页面进行配…...
c++最小步数模型(魔板)
C 最小步数模型通常用于寻找两个点之间的最短路径或最少步数。以下是一个基本的 C 最小步数模型的示例代码: #include<bits/stdc.h> using namespace std; const int N 1e5 5; vector<int> G[N]; int d[N]; bool vis[N];void bfs(int s) {queue<i…...
【每日一题Day337】LC460LFU 缓存 | 双链表+哈希表
LFU 缓存【LC460】 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象int get(int key) - 如果键 key 存在于缓存中,则获取键的值&#x…...

解决老版本Oracle VirtualBox 此应用无法在此设备上运行问题
问题现象 安装华为eNSP模拟器的时候,对应的Oracle VirtualBox-5.2.26安装的时候提示兼容性问题,无法进行安装,具体版本信息如下: 软件对应版本备注Windows 11专业工作站版22H222621eNSP1.3.00.100 V100R003C00 SPC100终结正式版…...

法规标准-UN R48标准解读
UN R48是做什么的? UN R48全名为关于安装照明和灯光标志装置的车辆认证的统一规定,主要描述了对各类灯具的布置要求及性能要求;其中涉及自动驾驶功能的仅有6.25章节【后方碰撞预警信号】,因此本文仅对此章节进行解读 功能要求 …...

自动化和数字化在 ERP 系统中意味着什么?
毋庸置疑,ERP系统的作用是让工作更轻松。它可以集成流程,提供关键分析,确保你的企业高效运营。这些信息可以提高你的运营效率,并将有限的人力资本重新部署到更有效、更重要的需求上。事实上,自动化和数字化是ERP系统最…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...