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

ops/2024/9/23 4:32:53/

前言:

🌟🌟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.ppmy.cn/ops/96857.html

相关文章

边缘计算下的图像识别:实现低延迟的实时智能处理

边缘计算下的图像识别在实现低延迟的实时智能处理方面展现出了显著的优势。以下是关于这一话题的详细分析&#xff1a; 一、边缘计算与图像识别的结合 1. 边缘计算的定义 边缘计算是一种分布式计算范式&#xff0c;它将计算任务、数据存储以及服务交付的功能从中心化的数据中…

《AI办公类工具PPT系列之二——iSlide AI》

一.简介 官网:iSlide- 让PPT设计简单起来 | PPT模板下载平台 iSlide AI是一款基于人工智能技术的PPT制作工具,它可以帮助用户快速高效地创建演示文稿 二.功能介绍 1. AI一键生成PPT 文档导入与解析:用户可以直接上传本地文档(如Word、Markdown、思维导图等),iSlide A…

Linux运维篇-yum命令报错 /lib64/libcurl.so.4相关

目录 项目场景&#xff1a;问题描述原因分析&#xff1a;解决方案&#xff1a; 项目场景&#xff1a; centos7&#xff0c;8&#xff0c;同样也适用openEuer&#xff0c;Kylin等redhat系的国产化操作系统 问题描述 在使用yum命令时报错&#xff1a; 主要报错信息为&#xff1…

Springboot企业人事管理系统---附源码121727

摘 要 由于数据库和数据仓库技术的快速发展&#xff0c;企业人事管理系统建设越来越向模块化、智能化、自我服务和管理科学化的方向发展。人事管理系统对处理对象和服务对象&#xff0c;自身的系统结构&#xff0c;处理能力&#xff0c;都将适应技术发展的要求发生重大的变化。…

SpringSecurity认证鉴权流程

SpringSecurity认证鉴权流程 SpringSecurity的认证流程SpringSecurity的鉴权流程将用户交给Spring Security管理主要涉及以下几个步骤&#xff1a; SpringSecurity的认证流程 用户请求&#xff1a; 用户向应用程序发起请求&#xff0c;通常是访问受保护的资源&#xff08;例如&…

《AOP实战》— 自定义注解

承接上文&#xff08;传送门 —>《面试必考》 — AOP-CSDN博客&#xff09;&#xff0c;在被面试官拷打的时候&#xff0c;会被问到一个致命问题&#xff1a;“你了解aop吗&#xff1f;有具体的使用经验吗&#xff1f;” 你&#xff1a;......... 言尽于此&#xff0c;此篇…

MySQL中的distinct和group by哪个效率更高?

前言 大家好&#xff0c;我是月夜枫~~ 一、distinct和group by的区别 1.1.作用方式和应用场景 ‌group by和‌distinct的主要区别在于它们的作用方式和应用场景。 group by用于对数据进行分组和聚合操作&#xff0c;通常与聚合函数&#xff08;如COUNT、SUM、AVG等&#xf…

【HeadFirst 设计模式】单例模式的C++实现

一、案例背景 书中给了一个巧克力工厂的例子&#xff0c;但是个人觉得关于单例模式书中给的例子过于简单&#xff0c;想要深入了解单例模式的小伙伴可以去看看这篇博客&#xff1a;【设计模式】单例模式的前世今生 二、案例分析 在很多时候&#xff0c;我们期望代码在运行过…