几大常用的排序算法

文章目录

  • 一、插入排序
  • 二、希尔排序(缩小增量排序)
  • 三、选择排序
  • 四、堆排序
  • 五、冒泡排序
  • 六、快速排序
    • 6.1 Hoare法
    • 6.2挖坑法
    • 快排的优化
    • 快排的非递归实现
  • 七、归并排序
    • 归并的非递归实现
  • 八、计数排序


一、插入排序

直接插入排序是一种简单的插入排序法,其基本思想是:
在待排序的元素中,假设第一个元素已有序,现将后面的元素与第一个元素作比较,比第一个元素小插入到前面已经排好的序列中,使得前面的元素有序。按照此法对所有元素进行插入,直到整个序列有序为止
动图演示:
在这里插入图片描述
代码如下所示:

    public static void insertSort(int[] array) {for (int i = 1; i < array.length; i++) {int tmp = array[i];int j = i - 1;for (; j >= 0; j--) {//加不加等号 能取决于这个排序的稳定性if (array[j] > tmp) {array[j + 1] = array[j];} else {break;}}array[j + 1] = tmp;}}
       时间复杂度:最坏情况下:O(N^2)最好情况下:O(N)空间复杂度:O(1)稳定性:稳定的排序

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

二、希尔排序(缩小增量排序)

希尔排序法又称缩小增量排序。希尔排序的基本步骤是:
1.先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…
2.当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成
动图演示:
在这里插入图片描述
先将待排序列进行预排序,使待排序列接近有序,然后再对该序列进行一次插入排序
代码如下:

    public static void shellSort(int[] array) {int gap = array.length;//进行预排序while (gap > 1) {gap = gap / 2;//对每一组进行插入排序shell(array,gap);}}private static void shell(int[] array,int gap) {for (int i = gap; i < array.length; i++) {int tmp = array[i];int j = i - gap;for (; j >= 0; j-=gap) {if (array[j] > tmp) {array[j + gap] = array[j];} else {break;}}array[j + gap] = tmp;}}

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

          稳定性:是一个不稳定的排序

三、选择排序

每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可
动图演示:
在这里插入图片描述
代码如下所示:

    public static void selectSort(int[] array) {for (int i = 0; i < array.length; i++) {//最小值int minIndex = i;int j = i + 1;for (; j < array.length; j++) {if(array[j] < array[minIndex]) {minIndex = j;}}swap(array, i, minIndex);}}private static void swap(int[] array, int i, int j) {int tmp = array[i];array[i] = array[j];array[j] = tmp;}
      时间复杂度:O(N^2)空间复杂度:O(1)稳定性:不稳定

四、堆排序

堆排序可以看之前的这篇博客【数据结构】之优先级队列(堆)

      时间复杂度:O(n*logN)空间复杂度:O(1)稳定性:不稳定

五、冒泡排序

左右两个相邻元素进行比较并交换
动图演示:
在这里插入图片描述
代码如下所示:

    public static void bubbleSort(int[] array) {for (int i = 0; i < array.length-1; i++) {boolean flg = false;for (int j = 0; j < array.length-1-i; j++) {if(array[j] > array[j + 1]) {swap(array, j, j + 1);flg = true;}}if(flg == false) {return;}}}
      时间复杂度:最好和最坏情况下都是O(N^2)空间复杂度:O(1)稳定性:稳定

六、快速排序

6.1 Hoare法

思路如下:
1、选出一个基准key,一般是最左边或是最右边的。
2、定义一个left和一个right,left从左向右走,right从右向左走。(需要注意的是:若选择最左边的数据作为key,则需要right先走;若选择最右边的数据作为key,则需要left先走)。
3、在走的过程中,若right遇到小于key的数,则停下,left开始走,直到left遇到一个大于key的数时,将left和right的内容交换,right再次开始走,如此进行下去,直到left和right最终相遇,此时将相遇点的内容与key交换即可。(选取最左边的值作为key)
4.此时key的左边都是小于key的数,key的右边都是大于key的数
5.将key的左序列和右序列再次进行这种单趟排序,如此反复操作下去,直到左右序列只有一个数据,或是左右序列不存在时,便停止操作,此时此部分已有序
动图演示:
在这里插入图片描述
代码如下所示:

    public static void quickSort(int[] array) {quick(array,0,array.length-1);}private static void quick(int[] array,int start,int end) {if(start >= end) {return;}int pivot = partitionHoare(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}private static int partitionHoare(int[] array,int left,int right) {int tmp = array[left];//基准int i = left;while (left < right) {//第一个判断防止数组越界,第二个是从右边找比基准小的while (left < right && array[right] >= tmp) {right--;}//第一个也是防止数组出现越界,第二个是从左边找比基准大的while (left < right && array[left] <= tmp) {left++;}//左边大的和右边小的进行交换swap(array,left,right);}//将相遇点和基准进行交换swap(array,i,left);return left;}

6.2挖坑法

思路:
挖坑法和Hoare法的思路类似
1.选出一个数据(一般是最左边或是最右边的)存放在key变量中,在该数据位置形成一个坑
2、定义一个left和一个right,left从左向右走,right从右向左走。(若在最左边挖坑,则需要right先走;若在最右边挖坑,则需要left先走)
后面的过程就和Hoare法类型
动图演示:
在这里插入图片描述
代码如下所示:

    private static int partition(int[] array,int left,int right) {int tmp = array[left];while (left < right) {while (left < right && array[right] >= tmp) {right--;}if(left >= right) {break;}array[left] = array[right];while (left < right && array[left] <= tmp) {left++;}if(left >= right) {break;}array[right] = array[left];}array[left] = tmp;return left;}

快排的优化

1.三数取中法找中间大数字的下标
2.递归到某个小的区间时使用插入排序
整体代码:

    public static void quickSort(int[] array) {quick(array,0,array.length-1);}private static void quick(int[] array,int start,int end) {if(start >= end) {return;}if(end-start+1 <= 10) {insertSort2(array, start, end);return;}//三数取中  index是中间大的数字 的 下标int index = middleNum(array,start,end);swap(array,index,start);int pivot = partition(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}private static void insertSort2(int[] array,int start,int end) {for (int i = start+1; i <= end; i++) {int tmp = array[i];int j = i-1;for (; j >= start ; j--) {if(array[j] > tmp) {array[j+1] = array[j];}else {break;}}array[j+1] = tmp;}}private static int middleNum(int[] array,int left,int right) {int mid = left+((right-left) >> 1);//int mid = (left+right)/2;if(array[left] < array[right]) {if(array[mid] < array[left]) {return left;}else if(array[mid] > array[right]) {return right;}else {return mid;}}else {if(array[mid] < array[right]) {return right;}else if(array[mid] > array[left]) {return left;}else {return mid;}}}private static int partition(int[] array,int left,int right) {int tmp = array[left];while (left < right) {while (left < right && array[right] >= tmp) {right--;}if(left >= right) {break;}array[left] = array[right];while (left < right && array[left] <= tmp) {left++;}if(left >= right) {break;}array[right] = array[left];}array[left] = tmp;return left;}
      时间复杂度: 最坏情况下:O(N^2)最好情况下:O(N*logN)空间复杂度:最坏情况下:O(N)最好情况下:O(logN)           稳定性:不稳定                  

快排的非递归实现

这里我们使用栈来实现非递归的快排

	public static void quickSortNor(int[] array) {Stack<Integer> stack = new Stack<>();int left = 0;int right = array.length-1;//找基准int pivot = partition(array,left,right);//基准左边的区间大于left进行入栈if(pivot-1 > left) {stack.push(left);stack.push(pivot-1);}//基准右边的区间小于right进行入栈if(pivot+1 < right) {stack.push(pivot+1);stack.push(right);}//判断栈是否为空 //不为空出两个下标再对左和右两个下边进行找基准操作重复以上操作直至数组有序为止while (!stack.isEmpty()) {right = stack.pop();left = stack.pop();pivot = partition(array,left,right);if(pivot-1 > left) {stack.push(left);stack.push(pivot-1);}if(pivot+1 < right) {stack.push(pivot+1);stack.push(right);}}}

七、归并排序

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并
动图演示:
在这里插入图片描述
代码如下所示:

    public static void mergeSort(int[] array) {mergeFunc(array,0,array.length-1);}private static void mergeFunc(int[] array,int left,int right) {if(left >= right) {return;}int mid = left + ((right - left) >> 1);mergeFunc(array,left,mid);mergeFunc(array,mid+1,right);//左边和右边分解完进行合并merge(array,left,mid,right);}private static void merge(int[] array,int left,int mid,int right) {int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;int[] tmp = new int[right - left + 1];int k = 0;//确保两个数组都有元素while (s1 <= e1 && s2 <= e2) {if(array[s1] < array[s2]) {tmp[k++] = array[s1++];}else {tmp[k++] = array[s2++];}}//看两个数组中 还有哪个有数据while (s1 <= e1) {tmp[k++] = array[s1++];}while (s2 <= e2) {tmp[k++] = array[s2++];}//拷贝回原来的数组for (int i = 0; i < k; i++) {array[i+left] = tmp[i];}}
    时间复杂度:O(n*logN)空间复杂度:O(N)稳定性:稳定

归并的非递归实现

    public static void mergeSortNor(int[] array) {int gap = 1;while (gap < array.length) {for (int i = 0; i < array.length; i=i+2*gap) {int left = i;int mid = left + gap - 1;if(mid >= array.length) {mid = array.length-1;}int right = mid + gap;if(right >= array.length) {right = array.length-1;}merge(array,left,mid,right);}gap *= 2;}}

八、计数排序

1.统计相同元素出现次数根据
2.统计的结果将序列回收到原来的序列中
3.计数排序只适用于范围集中且重复数据较高的数据
动图演示:
在这里插入图片描述
代码如下所示:

    public static void countSort(int[] array) {int min = array[0];int max = array[0];//找到最大值和最小值for (int i = 0; i < array.length; i++) {if(min > array[i]) {min = array[i];}if(max < array[i]) {max = array[i];}}//创建一个计数数组int[] count = new int[max-min+1];for (int i = 0; i < array.length; i++) {int index = array[i]-min;count[index]++;}//遍历这个计数数组int k = 0;for (int i = 0; i < count.length; i++) {while (count[i] !=0) {array[k] = i+min;k++;count[i]--;}}}
    时间复杂度:O(范围+n)范围 = max-min空间复杂度:O(范围)稳定性:稳定

在以上几种排序中属于稳定排序的只有:插入排序、冒泡排序、归并排序、计数排序

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

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

相关文章

spc x-bar 正态分布 echarts demo

使用echarts,elementUi,vue编写的spc分析的demo示例. 含x-bar和正态分布图,同一数据可以互转 chart.vue <template><div class"app-container"><el-row><el-col :span"4" class"button-container"><el-button clic…

【vue项目中点击下载】弹窗提示:离开此网站?系统可能不会保存您所做的更改,改为直接下载,不提示此弹窗内容,已解决

项目中用的是window.location.href实现下载 在Web浏览器中&#xff0c;当尝试通过window.location.href重定向到一个文件下载URL时&#xff0c;浏览器通常会显示一个确认对话框&#xff0c;询问用户是否要离开当前页面&#xff0c;因为下载的文件通常是在新窗口或新标签页中打…

程序员如何平衡主业与副业?

程序员的副业有哪些&#xff1f; 常见的有接私活&#xff0c;即外包一些软件项目来做&#xff0c;或者是写文章、拍教学视频、开直播等等。在这里&#xff0c;我更推荐程序员的副业是找个软件开发外包平台来接单&#xff0c;就是在工作之外接一下软件开发、外包项目等&#xf…

软件无线电系列——模拟无线电、数字无线电、软件无线电

本节目录 一、模拟无线电 二、数字无线电 1、窄带数字无线电 2、宽带数字无线电 三、软件无线电本节内容 一、模拟无线电 20世纪80年代的模拟体制(美国的AMPS/欧洲的TACS)被称为第一代移动通信&#xff0c;简称1G,主要目标是为在大范围内有限的用户提供移动电话服务。最主要的…

如何关闭 Visual Studio 双击异常高亮

[问题描述]&#xff1a; 最近 Visual Studio 更新后&#xff0c;双击选中关键字快要亮瞎我的眼睛了 &#x1f440;&#x1f440; [解决方法]&#xff1a; 摸索了一下&#xff0c;找到了关闭的方法&#xff1a;工具 → 选项 → 文本编辑器 → 常规&#xff0c;然后取消 勾选 sel…

vue3动态组件未渲染问题

渲染问题 component动态组件写法与vue2写法一致&#xff0c;代码如下&#xff1a; <component :is"componentName"/><script setup>import { ref } from vueimport account from ./user/account.vue// 组件名称const componentName ref(account)// 点击…

【算法】一类支持向量机OC-SVM(1)

【算法】一类支持向量机OC-SVM 前言一类支持向量机OC-SVM 概念介绍示例编写数据集创建实现一类支持向量机OC-SVM完整的示例输出 前言 由于之前毕设期间主要的工具就是支持向量机&#xff0c;从基础的回归和分类到后来的优化&#xff0c;在接触到支持向量机还有一类支持向量机的…

unity

Unity官方下载_Unity最新版_从Unity Hub下载安装 | Unity中国官网 Unity Remote - Unity 手册 登陆账号&#xff0c;找到一个3d 免费资源 3D Animations & Models | Unity Asset Store unity 里面window->package Manager 里面可以看到自己的asset &#xff0c;下载后…

MySQL 数据库压力测试

文章目录 前言1. 安装部署1.1 二进制安装1.2 源码安装 2. 服务器性能测试2.1 CPU2.2 内存2.3 磁盘 3. MySQL 基准测试3.1 参数解析3.2 压测命令3.3 输出解读3.4 结果分析 前言 Sysbench 是一个开源的多线程基准测试工具&#xff0c;也是目前使用最多的 MySQL 压力测试工具。本…

树莓派与电脑视频实时传输实现

编程环境 1、 树莓派 4B 2、 windows 编程语言 python 应用 tkinter scoket opencv 效果 视频同传 服务端视频初始化 服务端视频读取 windows 客户端接收视频流&#xff0c;队列存储 解析视频&#xff0c;存入队列 ui页面数据刷新 下载链接&#xff1a;https://…

elasticsearch篇:数据聚合

1.数据聚合 聚合&#xff08;aggregations&#xff09;可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f; 这些手机的平均价格、最高价格、最低价格&#xff1f; 这些手机每月的销售情况如何&#xff1f; 实现这些…

VUE3项目学习系列--Axios二次封装(五)

Axios中文文档 | Axios中文网 (axios-http.cn) Axios 是一个基于 promise 网络请求库&#xff0c;作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequ…

【洛谷 P8637】[蓝桥杯 2016 省 B] 交换瓶子 题解(贪心算法)

[蓝桥杯 2016 省 B] 交换瓶子 题目描述 有 N N N 个瓶子&#xff0c;编号 1 ∼ N 1 \sim N 1∼N&#xff0c;放在架子上。 比如有 5 5 5 个瓶子&#xff1a; 2 , 1 , 3 , 5 , 4 2,1,3,5,4 2,1,3,5,4 要求每次拿起 2 2 2 个瓶子&#xff0c;交换它们的位置。 经过若干次…

解释器模式(Interpreter Pattern)

解释器模式 说明 解释器模式&#xff08;Interpreter Pattern&#xff09;属于行为型模式&#xff0c;是指给定一门语言&#xff0c;定义它的语法&#xff08;文法&#xff09;的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。是一…

[NSSRound#18 Basic]web解析

文章目录 门酱想玩什么呢&#xff1f;Becomeroot 门酱想玩什么呢&#xff1f; 打开题目&#xff0c;加载完视频后要求我们给个游戏链接 点开评论区不难发现应该是想玩元梦之星&#xff0c;这里有个评论功能可以上传图片 我们随便输入点东西发现是插入并赋值到content元素里面 …

提示找不到MSVCP140.dll无法继续执行此代码的多种解决方法

当计算机系统在运行过程中突然提示“丢失MSVCP140.dll”这一错误信息时&#xff0c;意味着系统无法找到并加载这个至关重要的动态链接库文件。MSVCP140.dll是Microsoft Visual C Redistributable Package的一部分&#xff0c;对于许多基于Windows的应用程序来说&#xff0c;尤其…

Exam in MAC [容斥]

题意 思路 正难则反 反过来需要考虑的是&#xff1a; (1) 所有满条件一的(x,y)有多少对&#xff1a; x 0 时&#xff0c;有c1对 x 1 时&#xff0c;有c对 ...... x c 时&#xff0c;有1对 以此类推 一共有 (c2)(c1)/2 对 (2) 符合 x y ∈ S的有多少对&#xff1a…

openssl3.2 - note - Getting Started with OpenSSL

文章目录 openssl3.2 - note - Getting Started with OpenSSL概述笔记openssl 历史版本Configure 选项开关支持的OSopenssl 文档简介安装新闻每个平台的安装文档支持的命令列表配置文件格式环境变量 END openssl3.2 - note - Getting Started with OpenSSL 概述 看到官方文档…

物联网技术助力智慧城市转型升级:智能、高效、可持续

目录 一、物联网技术概述及其在智慧城市中的应用 二、物联网技术助力智慧城市转型升级的路径 1、提升城市基础设施智能化水平 2、推动公共服务智能化升级 3、促进城市治理现代化 三、物联网技术助力智慧城市转型升级的成效与展望 1、成效显著 2、展望未来 四、物联网技…

【C++初阶】C++入门(上)

C的认识 ①什么是C&#xff1f; ​ C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。 ​ 于是1982年&#xff0c;Bjarne Stroustrup&#xff08;本…