【算法篇】七大基于比较的排序算法精讲

目录

排序 

1.直接插入排序

2.希尔排序

3.直接选择排序

4.堆排序

5.冒泡排序

6.快速排序

7.归并排序


排序 

排序算法的稳定性:假设在待排序的序列中,有多个相同的关键字,经过排序后,这些关键字的先后顺序不发生改变,我们称这种排序算法是稳定的,否则是不稳定的。

把数据元素全部放在内存中进行排序我们称为内部排序

元素太多无法全部同时放在内存中,内存和外存相互结合使用的排序我们称为外部排序

 根据排序算法是否基于排序,可以将算法分为两种,而在基于排序的算法中最常见的算法有七种,分别是:直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序。

其中某些排序方法的实现思想相似,我们可进行如下分类:

插入排序:   1.直接插入排序           2.希尔排序

选择排序:   1.选择排序                  2.堆排序

交换排序:   1.冒泡排序                  2.快速排序

归并排序:    归并排序

1.直接插入排序

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

//1.插入排序public void insort(int[] arr){for(int i=1;i<arr.length;i++){int ret=arr[i];int j=i-1;for(;j>=0;j--){if(arr[j]>ret){arr[j+1]=arr[j];}else{break;}}arr[j+1]=ret;}}

直接插入排序的特性总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定

2.希尔排序

因为直接插入排序对于越有序的数组,时间复杂度越低,所以就有大佬发明了希尔排序,希尔排序的作用就是通过分组调整将无序的数组一步一步变得接近有序,最后组数为1时,数组有序。

希尔排序法又称缩小增量法。希尔排序法的基本思想是:

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


 

    //2.希尔排序public void shellSort(int[] arr){//gap表示每组元素之间间隔的位置。int gap= arr.length;while(gap>1){gap/=2;shell(arr,gap);}}private void shell(int[] arr, int gap) {for(int i=gap;i<arr.length;i++){int ret=arr[i];int j=i-gap;for(;j>=0;j-=gap){if(arr[j]>ret){arr[j+gap]=arr[j];}else{break;}}arr[j+gap]=ret;}}

 希尔排序的特性总结:
1. 希尔排序是对直接插入排序的优化。
2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
3. 希尔排序的时间复杂度与gap的取值有关,很难直接计算,根据Knuth在《计算机程序设计技巧》中的说明,当n很大时,时间复杂度可按O(N^1.25)到O(1.6*N^1.25)来计算。

4.稳定性:不稳定。

3.直接选择排序

基本思想:

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

    //3.直接选择排序public void chooseSort(int[] arr){for(int i=0;i<arr.length;i++){for(int j=i+1;j<arr.length;j++){if(arr[j]<arr[i]){int ret=arr[i];arr[i]=arr[j];arr[j]=ret;}}}}

特性总结:

1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定

4.堆排序

堆排序(Heapsort)是指:

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

详细代码实现过程请看我的上一篇文章对堆进行了详细讲解:【数据结构七】堆与PriorityQueue详解

特性总结:

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

5.冒泡排序

基本思想:

冒泡排序是一种典型的交换排序,根据序列中两个相邻记录键值的比较结果来对换这两个记录在序列中的位置 。交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

    //5.冒泡排序public void bubbleSort(int[] arr){for(int i=arr.length-1;i>0;i--){for(int j=0;j<i;j++){if(arr[j+1]<arr[j]){int tmp=arr[j+1];arr[j+1]=arr[j];arr[j]=tmp;}}}}

冒泡排序的特性总结:

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

6.快速排序

快速排序是在二叉树的前序遍历的基础上改进的一个算法,取基准值时要尽量保证左右两个区间的大小相等,这样的时间复杂度最低,在构建代码的时候我们尽量依据这一点来优化代码。

基本思想:

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

    //6.快速排序public void quickSort(int[] arr){quick(arr,0,arr.length-1);}//快速排序的主要实现private void quick(int[] arr, int left, int right) {if(right-left<1){return;}int prev=midnum(arr,left,right);int tmp=arr[prev];int cur1=left;int cur2=right;while(cur1<cur2){while (cur1<cur2&&arr[cur2]>=tmp){cur2--;}while (cur1<cur2&&arr[cur1]<=tmp){cur1++;}swap(arr, cur1, cur2);}swap(arr,left,cur1);quick(arr,left,cur1);quick(arr,cur1+1,right);}//交换两个元素位置private static void swap(int[] arr, int cur1, int cur2) {int tmp= arr[cur1];arr[cur1]= arr[cur2];arr[cur2]=tmp;}//创建一个方法求三个值的中间值,为了优化算法。private int midnum(int[] arr,int left,int right){int mid=(left+right)/2;if(arr[left]<arr[right]){if(arr[mid]<arr[left]){return left;}else if(arr[mid]>arr[right]){return right;}else{return mid;}}else{if(arr[mid]<arr[right]){return right;}else if(arr[mid]>arr[left]){return left;}else{return mid;}}}

特性总结:

1.快速排序整体的综合性能和使用场景都是比较好的。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(logN)
4. 稳定性:不稳定

7.归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。

基本思想:

将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

    //7.归并排序public void mergeSort(int[] arr){mergeSortFun(arr,0,arr.length-1);}private void mergeSortFun(int[] arr, int left, int right) {if(left>=right){return;}int mid=(left+right)/2;mergeSortFun(arr,left,mid);mergeSortFun(arr,mid+1,right);merge(arr,left,mid,right);}private void merge(int[] arr, int left, int mid, int right) {int s1=left;int e1=mid;int s2=mid+1;int e2=right;int[] tmpArr=new int[right-left+1];int k=0;while(s1<=e1&&s2<=e2){if(arr[s1]<=arr[s2]){tmpArr[k]=arr[s1];s1++;k++;}else{tmpArr[k]=arr[s2];s2++;k++;}}while(s1<=e1){tmpArr[k]=arr[s1];s1++;k++;}while(s2<=e2){tmpArr[k]=arr[s2];s2++;k++;}for(int i=0;i< tmpArr.length;i++){arr[i+left]=tmpArr[i];}}

特性总结:

1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(N)
4. 稳定性:稳定
 

欢迎大家点赞加关注啊!!!,随后会更新非基于比较的算法,基数排序,桶排序和计数排序。

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

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

相关文章

编程入行指南:从代码小白到技术大牛的“码农”奇幻漂流

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在这个飞速发展的信息时代&#xff0c;技术不断推陈出新&#xff0c;程序员若想保持行业翘楚地位&#xff0c;必须持续汲取新知、…

经典机器学习模型(一)感知机模型

经典机器学习模型(一)感知机模型 感知机可以说是一个相当重要的机器学习基础模型&#xff0c;是神经网络和支持向量机的基础。 感知机是一个二分类的线性分类模型&#xff0c;之所以说是线性&#xff0c;是因为它的模型是线性形式的。 从《统计学习方法》中&#xff0c;我们…

Docker Compose基本配置及使用笔记

Docker Compose基本配置及使用笔记 简介 Docker Compose 是一个用于定义和运行多个 Docker 容器应用程序的工具。它使用 YAML 文件来配置应用程序的服务&#xff0c;并通过简单的命令集管理这些服务的生命周期。 1.步骤1 代码如下&#xff1a;docker-compose.yml放在虚拟机roo…

前端项目,个人笔记(一)【Vue-cli - 定制化主题 + 路由设计】

目录 1、项目准备 1.1、项目初始化 1.2、elementPlus按需引入 注&#xff1a;使用cnpm安装elementplus及两个插件&#xff0c;会报错&#xff1a;vueelement-plus报错TypeError: Cannot read properties of null (reading isCE ) &#xff0c;修改&#xff1a; 测试&#…

Swin—Transformer学习笔记

一、网络框架 二、Patch Merging 图像长和宽减半&#xff0c;通道数增加一倍 三、W-MSA 目的&#xff1a;减少计算量 缺点&#xff1a;窗口之间无法进行信息交互 四、SW-MSA 目的&#xff1a;实现不同window之间的信息交互 为了不增加计算量&#xff0c;移动window并增加Ma…

【数据结构】二叉树OJ题(C语言实现)

✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅ ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨ &#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1f33f;&#x1…

【C#】int+null=null

C#语法&#xff0c;这玩意不报错 intnullnull&#xff0c;有点不合逻辑 (Int32)(bizRepair0rder.CreateTime. Value - regues.Mlodifylime.Value).TotalMinutes (Int32)(bizRepair0rder.CreateTime. Value - reques.llodifylime.Value).TotalMinutes nullstring是引用类型&…

机器学习-04-分类算法-03KNN算法

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中分类算法&#xff0c;本篇为分类算法与knn算法部分。 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 懂业务会选择合适的算法数据处理算法训练算法调优算法融合 算法评估持续调优工程化…

冲动是魔鬼,工作不顺心时不要把坏脾气带给家人

今天与一个跟踪了很久的客户准备签合同了&#xff0c;客户突然反悔&#xff0c;为此与他周旋了一整天&#xff0c;忙碌得一口水都没有喝。回到小区坐在车里抽着烟&#xff0c;久久不愿回家&#xff0c;只想一个人坐着&#xff0c;疲惫、无奈。这个月的奖金似乎又将成为泡影。 …

AI - 决策树模型

&#x1f914;决策树算法 决策树的思想来源可以追溯到古希腊时期&#xff0c;当时的哲学家们就已经开始使用类似于决策树的图形来表示逻辑推理过程。然而&#xff0c;决策树作为一种科学的决策分析工具&#xff0c;其发展主要发生在20世纪。 在20世纪50年代&#xff0c;美国兰…

Machine Vision Technology:Lecture5 Local feature:Corners角点

Machine Vision Technology&#xff1a;Lecture5 Local feature&#xff1a;Corners角点 Motivation&#xff1a;panorama stitching全景图拼接提取良好特征Feature points applications特征点应用Finding Corners找角点Corner Detection&#xff1a;Basic Idea角点检测基本思想…

【数据结构和算法初阶(C语言)】队列实操(概念实现+oj题目栈和队列的双向实现以及循环链表难点题目详解!)

目录 1. 队列的概念及结构 2.队列结构存在的意义应用 3.队列实现的结构选择 4.队列实现 5.队列对数据的处理 5.1队列初始化 5.2队尾入数据 5.3队头出数据 5.4获取队列尾部元素 5.5获取队列头部元素 5.6获取队列中元素个数 5.7检测队列是否为空 5.8销毁队列 6.循环队列补充 7.使…

【AcWing】蓝桥杯集训每日一题Day5|归并排序|离散化|二分|逆序数对|505.火柴排队(C++)

火柴排队 505. 火柴排队 - AcWing题库难度&#xff1a;中等时/空限制&#xff1a;1s / 128MB总通过数&#xff1a;2058总尝试数&#xff1a;4484来源&#xff1a;NOIP2013提高组算法标签贪心离散化树状数组归并排序 题目内容 涵涵有两盒火柴&#xff0c;每盒装有 n 根火柴…

广度优先算法(一篇文章讲透)

目录 引言 一、算法概述 二、算法步骤 1 初始化 2 循环处理 三、算法应用 1 图的最短路径问题 2 网络爬虫 3 社交网络分析 4 游戏路径搜索 事例 四、算法特点与性能 五、性能优化 1 剪枝策略&#xff1a; 2 使用高效的数据结构&#xff1a; 3 并行化处理&#…

qt vs 编程 字符编码 程序从源码到编译到显示过程中存在的字符编码及隐藏的字符编码转换

理解字符编码&#xff0c;请参考&#xff1a;unicode ucs2 utf16 utf8 ansi GBK GB2312 CSDN博客 了解windows字符显示必须了解locale概念 参考&#xff1a;揭密 Windows 上的各种 locale - 知乎 汉字&#xff08;或者说多字节字符&#xff09;的存放需求&#xff0c;是计算…

理解数学概念——同伦和简单连通域

1. 同伦(homotopy) 1.1 homotopy[hɒməʊˈtɒpi] n. (1) <<The Oxford English Dictionary>>第二版&#xff1a; [数学专用术语&#xff0c;这个词由德语homotopie改造而来&#xff0c;(Dehn & Heegaard Analysis Situs in Encykl.d.math.Wiss.(1907) I…

【滤波专题-第8篇】ICA降噪方法——类EMD联合ICA降噪及MATLAB代码实现(以VMD-ICA为例)

今天来介绍一种效果颇为不错的降噪方法。&#xff08;针对高频白噪声&#xff09; 上一篇文章我们讲到了FastICA方法。在现实世界的许多情况下&#xff0c;噪声往往接近高斯分布&#xff0c;而有用的信号&#xff08;如语音、图像特征等&#xff09;往往表现出非高斯的特性。F…

测试环境搭建整套大数据系统(十一:docker部署superset,无密码登录嵌入html,http改为https)

一&#xff1a;安装docker 参考文档 https://blog.csdn.net/weixin_43446246/article/details/136554243 二&#xff1a;安装superset 下载镜像。 拉取镜像&#xff08;docker pull amancevice/superset&#xff09; 查看镜像是否下载完成&#xff08;docker images&#xf…

如何检测无源晶振过驱?晶振过驱怎么办?

无源晶振(Passive Crystal Oscillator)是一种使用晶体元件来生成稳定频率的振荡器&#xff0c;它不像有源振荡器(如时钟芯片)那样需要外部电源。检测无源晶振是否过驱通常需要通过测量其输出波形和频率&#xff0c;与期望的规格进行比较。 如何检测无源晶振过驱&#xff1a; …

Linux——线程池

线程池的概念 线程池也是一种池化技术&#xff0c;可以预先申请一批线程&#xff0c;当我们后续有任务的时候就可以直接用&#xff0c;这本质上是一种空间换时间的策略。 如果有任务来的时候再创建线程&#xff0c;那成本又要提高&#xff0c;又要初始化&#xff0c;又要创建数…