排序算法:插入排序、冒泡排序、选择排序、希尔排序、堆排序、快速排序

news/2024/5/12 7:44:45/文章来源:https://blog.csdn.net/qq_53130059/article/details/127713510

排序算法相关总结,涉及的排序算法有:插入排序、冒泡排序、选择排序、希尔排序、堆排序、快速排序。

这里写目录标题

      • 1.插入排序
      • 2.冒泡排序
      • 3.选择排序
      • 4.希尔排序
      • 5.堆排序
      • 6.快速排序
      • 总结


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


1.插入排序

思路:当前元素左边为有序序列,右边为待排序序列,当前元素与有序数列的最后一个元素依次比较,如果比它大,则不动,若比它小,则有序序列最后一个元素后移一位,为当前元素空出一个坑位,循环比较,直到找到当前元素的位置。

图示:

在这里插入图片描述

代码:时间复杂度O(n^2),空间复杂度O(1)

//插入排序public class InsertSort {public static void main(String[] args) {//验证int[] arr = new int[]{5, 4, 3, 8, 4, 1, 6, 0, 9, 10};insertSort(arr);for (int i : arr) {System.out.print(i + " ");}}//插入排序public static void insertSort(int[] arr) {for (int i = 0; i < arr.length; i++) {//有序区间为 [0,i)int k = i;//记录i下标当前值 与有序序列比较int tmp = arr[i];//如果下标合法且比tmp大 则元素后移while (k > 0 && tmp < arr[k - 1]) {arr[k] = arr[k - 1];k--;}arr[k] = tmp;}}

2.冒泡排序

冒泡!!!好的解释完了

图示:
在这里插入图片描述

代码: 老老老朋友了,时间复杂度O(n^2),空间复杂度O(1)

//冒泡排序public class BubbleSort {public static void main(String[] args) {//验证int[] arr = new int[]{5, 4, 3, 8, 4, 1, 6, 0, 9, 10};bubblesort(arr);for (int i : arr) {System.out.print(i + " ");}}//冒泡排序public static void bubblesort(int[] arr) {for (int i = 0; i < arr.length; i++) {//判断该趟是否发生交换boolean flag = true;for (int j = 0; j < arr.length - 1 - i; j++) {if (arr[j] > arr[j + 1]) {//交换int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;flag = false;}}//如果没有发生交换 则说明后面的已经有序 结束循环if (flag) {break;}}}

3.选择排序

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

图示:
在这里插入图片描述

代码: 时间复杂度O(n^2),空间复杂度O(1)

//选择排序(将找到的较大元素放置末尾 和上图演示的反着的 但不影响理解)public class SelectSort {public static void main(String[] args) {//验证int[] arr = new int[]{5, 4, 3, 8, 4, 1, 6, 0, 9, 10};selectSort(arr);for (int i : arr) {System.out.print(i + " ");}}public static void selectSort(int[] arr) {for (int i = 0; i < arr.length - 1; i++) {int maxIdx = 0;for (int j = 1; j < arr.length - i; j++) {if (arr[j] > arr[maxIdx]) {maxIdx = j;}}//swapint idx = arr.length - 1 - i;int tmp = arr[maxIdx];arr[maxIdx] = arr[idx];arr[idx] = tmp;}}

4.希尔排序

我们知道插入排序元素越有序效率越高,当全部有序时,效率达到O(n),希尔排序正是利用这个特点,进行了大量的分组插入排序,从而达到有序目的。
基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后取重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

图示:

在这里插入图片描述

动图:

在这里插入图片描述

代码: 时间复杂度O(n^2),空间复杂度O(1)

//希尔排序public class ShellSort {public static void main(String[] args) {//验证int[] arr = new int[]{5, 4, 3, 8, 4, 1, 6, 0, 9, 10, -5, 50, 33, 41, 7, 30, 45, 11};shellSort(arr);for (int i : arr) {System.out.print(i + " ");}}public static void shellSort(int[] arr) {int gap = arr.length / 2;while (true) {for (int i = gap; i < arr.length; i++) {int tmp = arr[i];int k = i;while (k - gap >= 0 && tmp < arr[k - gap]) {arr[k] = arr[k - gap];k -= gap;}arr[k] = tmp;}if (gap == 1) {break;}gap /= 2;}}

5.堆排序

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。

图示:
在这里插入图片描述

代码: 时间复杂度O(N*log(N)),空间复杂度O(1)

//堆排序public class HeapSort {public static void main(String[] args) {//验证int[] arr = new int[]{5, 4, 3, 8, 4, 1, 6, 0, 9, 10, -5, 50, 33, 41, 7, 30, 45, 11};heapSort(arr);for (int i : arr) {System.out.print(i + " ");}}public static void heapSort(int[] arr) {//建堆createHeap(arr);for (int i = 0; i < arr.length - 1; i++) {swap(arr, 0, arr.length - 1 - i);adjustDown(arr, 0, arr.length - 1 - i);}}public static void createHeap(int[] arr) {for (int i = (arr.length - 1 - 1) / 2; i >= 0; i--) {adjustDown(arr, i, arr.length);}}//在无序区间内进行向下调整public static void adjustDown(int[] arr, int idx, int len) {while (2 * idx + 1 < len) {int maxIdx = 2 * idx + 1;int rightIdx = maxIdx + 1;if (rightIdx < len && arr[maxIdx] < arr[rightIdx]) {maxIdx = rightIdx;}if (arr[maxIdx] < arr[idx]) {break;}swap(arr, maxIdx, idx);//更新idx = maxIdx;}}private static void swap(int[] arr, int i, int j) {//swapint tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}

6.快速排序

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

代码:时间复杂度O(n*logn),空间复杂度O(log n)

    public static void quickSort(int[] arr, int from, int to) {//判断是否结束if (to - from < 1) {return;}//划分方法 下面有实现int div = partition(arr, from, to);quickSort(arr, from, div - 1);quickSort(arr, div + 1, to);}

将区间按照基准值划分为左右两半部分的常见方式有:

1.Hoare:

1.选出一个基准值pivot,一般是最左边或最右边的为基准值
2.找到右边第一个小于pivot的值
3.找到左边第一个大于pivot的值
4.交换两个值,然后重复步骤2、3
5.将基准值放到i == j 的位置,返回基准值下标

    public static int partition(int[] arr, int left, int right) {int i = left;int j = right;int pivot = arr[left];while (i < j) {//注意这里判断j与先判断i的区别//先判断j:当i == j时 arr[i] == arr[j] <= povit//先判断i:当i == j时 arr[i] == arr[j] >= povitwhile (i < j && arr[j] >= povit) {j--;}while (i < j && arr[i] <= povit) {i++;}swap(arr, i, j);}swap(arr, left, i);return i;}

图示:
在这里插入图片描述

2.挖坑法:

1.选出一个基准值pivot,一般是最左边或最右边的为基准值 让它做坑位
2.找到右边第一个小于pivot的值 将该值放入坑位 该值的原下标做为新坑位
3.找到左边第一个大于pivot的值 将该值放入坑位 该值的原下标做为新坑位
4.重复步骤2、3
5.将基准值放到i == j 的位置,返回基准值下标

    public static int partition(int[] arr, int left, int right) {int i = left;int j = right;int pivot = arr[left];while (i < j) {while (i < j && arr[j] >= pivot) {j--;}arr[i] = arr[j];while (i < j && arr[i] <= pivot) {i++;}arr[j] = arr[i];}arr[i] = pivot;return i;}

图示:

在这里插入图片描述

3.前后指针法:

1.选出一个基准值pivot,一般是最左边或最右边的为基准值
2.规定[0,pre)为小于pivot的范围,[pre,right]为大于pivot的范围
3.遍历找小于pivot的值,交换arr[pre]和该值,然后pre++
4.最后将pivot值放入数组,放哪里合适呢?当然是pre - 1处,这样确保它的右边大于等于pivot,左边小于等于pivot

    public static int partition(int[] arr, int left, int right) {int pre = left + 1;int pivot = arr[left];for (int cur = pre; cur <= right; cur++) {if (arr[cur] < pivot) {swap(arr, cur, pre);pre++;}}swap(arr, pre - 1, left);return pre - 1;}

总结

排序算法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
插入排序O(n^2)O(n^2)O(n)O(1)稳定
冒泡排序O(n^2)O(n^2)O(n)O(1)稳定
选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定
希尔排序O(n^1.3)O(n^2)O(n)O(1)不稳定
堆排序O(n*log n)O(n*log n)O(n*log n)O(1)不稳定
快速排序O(n*log n)O(n^2)O(n*log n)O(log n)不稳定

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

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

相关文章

缓冲区的管理

文章目录什么是缓冲区&#xff1f;有什么作用&#xff1f;单缓冲单缓冲和双缓冲通信时的区别循环缓冲区缓冲池什么是缓冲区&#xff1f;有什么作用&#xff1f; 缓冲区是一个存取区域&#xff0c;可以由专门的硬件寄存器组成&#xff0c;也可以用内存作为缓冲区&#xff0c;本节…

Python中的几种推导式用法,先收藏再说......

嗨害大家好鸭&#xff01;我是小熊猫❤ 今天我们来整点非常干的干货&#xff1a; 源码、资料电子书点击此处 Python 推导式是一种独特的数据处理方式&#xff0c; 可以从一个数据序列构建另一个新的数据序列的结构体。 Python 支持各种数据结构的推导式&#xff1a; 列表(li…

D. Maximum Sum on Even Positions(最大连续字段和)

Problem - 1373D - Codeforces 题意: 给你一个由n个整数组成的数组a。数组的索引从零开始&#xff08;即第一个元素是a0&#xff0c;第二个是a1&#xff0c;以此类推&#xff09;。 你最多可以扭转这个数组的一个子数组&#xff08;连续子段&#xff09;。回顾一下&#xff0c…

[附源码]计算机毕业设计JAVAjsp不回头药店药品管理系统

[附源码]计算机毕业设计JAVAjsp不回头药店药品管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SS…

【Prometheus】什么是prometheus?prometheus简介

本文目录 一、什么是prometheus&#xff1f; 二、体系结构概述 三、适用场景 四、不适用的场景 一、什么是prometheus&#xff1f; Prometheus官网 Prometheus开源代码 From metrics to insight Power your metrics and alerting with the leading open-source monitoring…

随想录一刷Day48——动态规划

文章目录Day48_动态规划29. 打家劫舍30. 打家劫舍 II31. 打家劫舍 IIIDay48_动态规划 29. 打家劫舍 198. 打家劫舍 思路&#xff1a; 题目的关键是&#xff0c;不能偷相邻的两个屋子&#xff0c;即只能偷上一个屋子不偷当前屋子&#xff0c;或者不偷上一个屋子偷当前屋子。 d…

LeetCode刷题(python版)——Topic57插入区间

一、题设 给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表。 在列表中插入一个新的区间&#xff0c;你需要确保列表中的区间仍然有序且不重叠&#xff08;如果有必要的话&#xff0c;可以合并区间&#xff09;。 示例 1&#xff1a; 输入&#xff1a;interva…

ServletConfig和ServletContext接口

一、ServletConfig接口详解 1、简介 Servlet 容器初始化 Servlet 时&#xff0c;会为这个 Servlet 创建一个 ServletConfig 对象&#xff0c;并将 ServletConfig 对象作为参数传递给 Servlet 。通过 ServletConfig 对象即可获得当前 Servlet 的初始化参数信息。一个 Web 应用中…

【仿牛客网笔记】 Redis,一站式高性能存储方案——Redis入门

Redis可以开发对性能要求较高的功能。还可以利用Redis重构我们现有的功能。 NoSQL关系型数据库之外的统称。 快照有称为RDB 以快照的形式 不适合实时的去做&#xff0c;适合一段时间做一次。 日志又称AOF 以日志的形式每执行一次就存入到硬盘中&#xff0c;可以做到实时的存储以…

【python的静态方法,classmethod方法和__call___魔法方法】

classmethod魔法方法和staticmethodstaticmethod&#xff0c;静态方法classmethod&#xff0c;绑定类方法__call__&#xff0c;可调用类类方法staticmethod&#xff0c;静态方法 在python中&#xff0c;使用静态方法可以实现不需要实例化对象的绑定就可以直接调用的函数&#…

【Unity3D】游戏物体操作 ④ ( 选中多个游戏物体操作 | 复制选中物体 | 聚焦选中物体 | 激活、禁用选中物体 | 对齐选中物体 )

文章目录一、选中多个游戏物体操作1、Scene 场景窗口选中多个物体2、Hierarchy 层级窗口选中多个物体二、复制选中物体1、使用 " Ctrl D " 快捷键复制物体2、使用 右键菜单 | Duplicate 选项复制三、聚焦选中物体四、激活、禁用选中物体五、对齐选中物体一、选中多个…

计算机组成原理浮点数表示

浮点数表示 浮点数的表示分为阶码和尾数&#xff1b; 比如3.026*1011;阶码是11;尾数是3.026&#xff1b; 对于阶码&#xff1a; 阶符为正&#xff0c;小数点向后移n位&#xff08;n表示阶的大小&#xff09;; 阶符为负&#xff0c;小数点向前移n位&#xff08;n表示阶的大小&a…

AttributeError: ‘bytes‘ object has no attribute ‘encode‘异常解决方案

AttributeError: bytes object has no attribute encode是&#xff1a;“字节”对象没有属性的编码的意思。 很明显&#xff0c;是编码格式的问题&#xff0c;例如&#xff1a;已经是byte格式的字符串类型&#xff0c;二次进行encode的时候就会出现这个bug&#xff0c;示例如下…

【猿创征文】Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo

前两篇文章分享了基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli&#xff0c;但在中大型的企业级项目中&#xff0c;通常会自主搭建这些脚手架或加速器。优雅哥希望每位前端伙伴能知其所以然&#xff0c;故接下来的文…

基础IO(下)——Linux

文章目录1. 理解文件系统1.2 背景知识1.2 inode vs 文件名1.3 软硬链接2. 动态库和静态库2.1 静态库.a2.1.1 如果想写一个库&#xff1f;&#xff08;编写库的人的角度&#xff09;2.1.2如果我把库给别人&#xff0c;别人怎么用呢&#xff1f;&#xff08;使用库的人的角度&…

中医-通过舌象判断身体状况

本文分享通过舌象判断身体的整体状况&#xff08;中医角度&#xff09;&#xff0c;得出一个可供辨证的参考&#xff0c;并且可以根据舌象做出相关的饮食调整&#xff0c;本文主讲理论&#xff0c;相关舌象图片易引人不适&#xff0c;如需找相关图片&#xff0c;可根据本文中的…

git rebase实战

例如&#xff0c; 在B分支上做rebase。 git rebase 之前确保当前分支是最新的。 切换到B分支&#xff1a; 1.git rebase origin/master(以origin/master分支为基线&#xff0c;合入master分支的修改到origin/master)此时会提示冲突文件 2.对冲突文件进行修改 3.git add 4.git …

网络面试-ox07http中的keep-alive以及长/短连接

非Keep-Alive: 早起HTTP1.0, 浏览器发起http请求需要与服务器建立新的TCP连接&#xff0c;请求处理后连接立即关闭。 缺点&#xff1a;每个这样的连接&#xff0c;客户端与服务器都要分配TCP的缓冲区和变量&#xff0c;这给服务器带来严重的负担。 Keep-Alive: 默认持久连接&am…

上海亚商投顾:沪指录得6连阳 两市成交再度破万亿

上海亚商投顾前言&#xff1a;无惧大盘大跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 三大指数今日横盘震荡&#xff0c;收盘集体小幅上扬&#xff0c;日K线均录得6连阳。虚拟现实概念股集体拉升&#…

最详细、最全面的【Java日志框架】介绍,建议收藏,包含JUL、log4j、logback、log4j2等所有主流框架

前言 本文为 【Java日志框架】 相关知识&#xff0c;之前已经介绍了Java日志框架的发展历史&#xff1a;Java日志框架的发展历史。 这篇文章将对日志的概念与作用&#xff0c;JUL日志框架&#xff0c;Log4j日志框架&#xff0c;Logback日志框架&#xff0c;Log4j2日志框架&…