【数据结构】关于冒泡排序,选择排序,插入排序,希尔排序,堆排序你到底了解多少???(超详解)

本文主要是介绍【数据结构】关于冒泡排序,选择排序,插入排序,希尔排序,堆排序你到底了解多少???(超详解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

🌟🌟Hello家人们,这期讲解排序算法的原理,希望你能帮到屏幕前的你。

🌈上期博客在这里:http://t.csdnimg.cn/I1Ssq

🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客

目录

📚️1.排序的概念和运用 

1.1排序的概念

1.2排序的运用

1.3常见的排序算法

 📚️2.常见排序算法的实现

2.1插入排序

2.2希尔排序 

2.3选择排序

2.4冒泡排序 

2.5堆排序 

📚️3.排序总结


📚️1.排序的概念和运用 

1.1排序的概念

排序所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

对于稳定性举例: 假如两个人考了一样的分数,那么先交卷的同学成绩因该排在后交卷的同学的前面,这样才符合常理逻辑。

内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

1.2排序的运用

例如:在通常我们在购物时,总会在界面顶部看到按照价格由低到高,或者由高到低,还有我们平时经常关注的中国大学实力排名等等,又要运用到排序,甚至当我们大打克牌的时候对其进行从小到大的排序,由此可见排序在日常生活中无处不在。

1.3常见的排序算法

这里小编将讲解前五个排序。 

 📚️2.常见排序算法的实现

2.1插入排序

1.插入排序思想:

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的想。

2.图解:

3.代码实现:

public static void InsertSort(int array[]){int temp=0;int i;int j;for (j = 1; j < array.length; j++) {temp=array[j];//此时进行大小判断for ( i = j-1; i >=0 ; i--) {if(temp<array[i]){//赋值array[i+1]=array[i];}else {break;}}array[i+1]=temp;}}

这里小编设置了temp表示存储空间,i的值开始都为j-1然后每次递减,与对应的数字进行比较,然后发现对应的位置就将存储的数值,插入其中,j++直到队尾。

 4.插入排序总结

1. 元素集合越接近有序,直接插入排序算法的时间效率越高


2. 时间复杂度:

最坏情况:O(N^2)   (5    4    3    2    1)完全逆序

最好情况:O(N)       (1    2    3    4    5)完全顺序


3. 空间复杂度:O(1),它是一种稳定的排序算法


4. 稳定性:稳定

2.2希尔排序 

1.希尔排序法的思想:

先选定一个整数,把待排序文件中所有记录分成多个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序

2.图解:

其实就是进行分组,然后每组进行插入排序即可,因为最后的分组为1,然而此时的数据已经接近一个有序的排列,所以减少了排序时间。

3.代码实现:

public static void ShellSort(int[] array){int gap= array.length;while (gap>=1){gap/=2;Shell(array,gap);}}public static void Shell(int[] array,int gap){int temp=0;int i;int j;for (j = gap; j < array.length; j++) {temp=array[j];//此时进行大小判断for ( i = j-gap; i >=0 ; i=i-gap) {if(temp<array[i]){//赋值array[i+gap]=array[i];}else {break;}}array[i+gap]=temp;}}

小编在这里设置了两个方法,一个负责进行分组,小编就不在过多赘述,对于另一个方法,这里j的开始为gap是应为分组为gap组,然后每组的第二个元素就为gap下标,i也要减去gap,大家看可以照图来看。

4.希尔排序的总结:

1. 希尔排序是对直接插入排序的优化。


2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。


3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定

4.希尔排序是不稳定的排序

2.3选择排序

1.选择排序基本思想:

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

2.图解:

3.代码实现:

public static void SelectSort(int[] array){for (int k = 0; k < array.length-1; k++) {int minIndex=k;for (int j = k+1; j < array.length ; j++) {if(array[j]<array[minIndex]){minIndex=j;}}int temp=array[k];array[k]=array[minIndex];array[minIndex]=temp;}}

注意:每次更新时,minindex下标也要跟着进行更新。

4.选择排序总结:

1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用


2. 时间复杂度:O(N^2)(不管排序情况咋样)


3. 空间复杂度:O(1)


4. 稳定性:不稳定

2.4冒泡排序 

1.冒泡排序思路:

基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,在冒泡排序中通过相邻两个数字的比较,若前面的更小,那么将两者进行交换,然后下标往后移。

2.图解:

3.代码实现:

 public static void BubbleSort(int[] array){for (int i = 0; i <array.length-1 ; i++) {boolean bool=false;for (int j = 0; j < array.length-1-i; j++) {if(array[j]>array[j+1]){swap(j,j+1,array);bool=true;}}if(bool==false){return;}}}

 注意:这里设置了布尔类型,若没有进行交换,则表示这组数据已经有序了,那么此时bool为true,在一次操作后进行判断,为true就直接跳出循环,反之继续进行下一次循环。即对冒泡排序的优化。

4.冒泡排序总结: 

1. 冒泡排序是一种非常容易理解的排序
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:稳定

2.5堆排序 

1.堆排序思路:

堆排序(Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆 来进行选择数据需要注意的是排升序要建大堆,排降序建小堆。

2.图解: 

在这里主要是,先将所给的数据建成一个大根堆,因为堆顶元素肯定是最大的,然后进行与末尾元素进行交换,然后忽视队尾最大元素,再次进行一次向下调整为大根堆,然后又进行与队尾元素交换。

3.代码实现:

public static void HeapSort(int[] array){createBigheap(array);for (int i = array.length-1; i >0 ; i--) {swap(0, i,array);shiftdown(0,array,i-1);}}//创建一个大根堆public static void createBigheap(int[] array){for (int parent = (array.length-2)/2; parent >=0 ; parent--) {shiftdown(parent,array, array.length-1);}}//向下调整public static void shiftdown(int parent,int[] array,int end){int child=parent*2+1;while (child< end){if(array[child]<array[child+1]&&(child+1)<=end){child++;}if(array[parent]<array[child]){int temp=array[parent];array[parent]=array[child];array[child]=temp;}parent=child;child=parent*2+1;}}

这里的向下调整和创建一个大根堆,小编在上一期已经讲解过了,就不再过多赘述。

注意:这里主要是在调用传参的时候,因为要忽略交换后队尾最大元素,所以每次进行向下调整后都要进行边界的调整。

4.堆排序总结:

1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定

📚️3.排序总结

💬💬小编这期主要讲述了对于七大排序的前五个,通过讲解思路,以及画图的方式进行思路分析,以及代码的实现。

对于排序算法来说,主要是抓住每种排序的思想,以及排序的方式,这里可以推荐通过画图的方式进行分析,效果事半功倍~~~

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!


                                💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。

                                                         😊😊  期待你的关注~~~ 

 

这篇关于【数据结构】关于冒泡排序,选择排序,插入排序,希尔排序,堆排序你到底了解多少???(超详解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1091167

相关文章

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Linux内核之内核裁剪详解

《Linux内核之内核裁剪详解》Linux内核裁剪是通过移除不必要的功能和模块,调整配置参数来优化内核,以满足特定需求,裁剪的方法包括使用配置选项、模块化设计和优化配置参数,图形裁剪工具如makeme... 目录简介一、 裁剪的原因二、裁剪的方法三、图形裁剪工具四、操作说明五、make menuconfig

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

详解Java中的敏感信息处理

《详解Java中的敏感信息处理》平时开发中常常会遇到像用户的手机号、姓名、身份证等敏感信息需要处理,这篇文章主要为大家整理了一些常用的方法,希望对大家有所帮助... 目录前后端传输AES 对称加密RSA 非对称加密混合加密数据库加密MD5 + Salt/SHA + SaltAES 加密平时开发中遇到像用户的

Springboot使用RabbitMQ实现关闭超时订单(示例详解)

《Springboot使用RabbitMQ实现关闭超时订单(示例详解)》介绍了如何在SpringBoot项目中使用RabbitMQ实现订单的延时处理和超时关闭,通过配置RabbitMQ的交换机、队列和... 目录1.maven中引入rabbitmq的依赖:2.application.yml中进行rabbit

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

SpringBoot使用Apache POI库读取Excel文件的操作详解

《SpringBoot使用ApachePOI库读取Excel文件的操作详解》在日常开发中,我们经常需要处理Excel文件中的数据,无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到... 目录项目背景依赖导入读取Excel模板的实现代码实现代码解析ExcelDemoInfoDTO 数据传输