冒泡、选择、堆排序

  • 前言
  • 冒泡排序
    • 冒泡排序-优化1
    • 冒泡排序-优化2
    • 复杂度与稳定性
  • 选择排序
    • 复杂度与稳定性
  • 堆排序
    • 堆排序图解
    • 堆排序实现
    • 复杂度与稳定性

经典的十大排序算法!

前言

请务必看一下这个:排序算法前置知识+代码环境准备。

当上面的内容都准备好以后,那就从冒泡排序开始吧。

冒泡排序

冒泡排序也叫做起泡排序

执行流程

  • ① 从头开始比较每一对相邻元素,如果第1个比第2个大,就交换它们的位置
    执行完一轮后,最未尾那个元素就是最大的元素。
  • ② 忽略①中曾经找到的最大元素,重复执行步骤①,直到全部元素有序。

这是一个标准的冒泡排序。

/*** 冒泡排序-无优化*/
public class BubbleSort1<T extends Comparable<T>> extends Sort<T>{@Overrideprotected void sort() {for (int end = array.length - 1; end > 0; end--) {for (int begin = 1; begin <= end; begin++) {if (cmp(begin, begin - 1) < 0) {swap(begin, begin - 1);}}}}}

冒泡排序-优化1

这个优化并不会提高冒泡排序的平均性能,只是针对极端条件进行处理

如果序列已经完全有序,可以提前终止冒泡排序。

/*** 冒泡排序-优化1* 如果序列已经完全有序,可以提前终止冒泡排序*/
public class BubbleSort2<T extends Comparable<T>> extends Sort<T>{@Overrideprotected void sort() {for (int end = array.length - 1; end > 0; end--) {boolean sorted = true;for (int begin = 1; begin <= end; begin++) {if (cmp(begin, begin - 1) < 0) {swap(begin, begin - 1);sorted = false;}}if (sorted) break;}}}

冒泡排序-优化2

这个优化是在优化1的基础上,增大极端条件的范围,从完全有序变为尾部局部有序

如果序列尾部已经局部有序,可以记录最后1次交换的位置,减少比较次数。

/*** 冒泡排序-优化2* 如果序列尾部已经局部有序,可以记录最后1次交换的位置,减少比较次数*/
public class BubbleSort3<T extends Comparable<T>> extends Sort<T>{@Overrideprotected void sort() {for (int end = array.length - 1; end > 0; end--) {// 设为1是因为:如果这轮遍历一次交换都没进行// 则说明序列后面已经有序, 则 end = sortedIndex = 1// end--后等于0,会直接跳出循环int sortedIndex = 1; for (int begin = 1; begin <= end; begin++) {if (cmp(begin, begin - 1) < 0) {swap(begin, begin - 1);// 记录最后1次交换的位置,减少比较次数sortedIndex = begin;}}end = sortedIndex;}}}

复杂度与稳定性

再强调一下,请务必看一下这个:排序算法前置知识+代码环境准备。

最坏、平均时间复杂度: O(n2)O(n^2)O(n2)
最好时间复杂度: O(n)O(n)O(n)
空间复杂度: O(1)O(1)O(1)
冒泡排序属于 In-place
冒泡排序属于稳定的排序算法

稍有不慎,稳定的排序算法也能被写成不稳定的排序算法,比如下面的冒泡排序代码是不稳定的。

选择排序

执行流程:

  • ① 从序列中找出最大的那个元素,然后与最未尾的元素交换位置
    执行完一轮后,最未尾的那个元素就是最大的元素。
  • ② 忽略①中曾经找到的最大元素,重复执行步骤①。
/*** 选择排序*/
public class SelectionSort<T extends Comparable<T>> extends Sort<T> {@Overrideprotected void sort() {for (int end = array.length - 1; end > 0; end--) {int max = 0;for (int begin = 1; begin <= end; begin++) {if (cmp(max, begin) < 0) {max = begin;}}swap(max, end);}}}

生成 20000 个取值在[1, 10000] 的随机数进行排序:

选择排序的交换次数要远远少于冒泡排序,平均性能优于冒泡排序

复杂度与稳定性

  • 最好、最坏、平均时间复杂度:O(n2)O(n^2)O(n2)
  • 空间复杂度:O(1)O(1)O(1)
  • 选择排序属于不稳定排序

选择排序是否还有优化的空间?

  • 使用堆来选择最大值,可以大大提高选择速度

堆排序

堆排序的前提是了解 堆的知识点。

执行流程:

  • ① 对序列进行原地建堆(heapify)
  • ② 重复执行以下操作(依次取出堆中最大值,并删除),直到堆的元素数量为 1
    • 交换堆顶元素与堆尾元素(把最大值放到最后面)
    • 堆的元素数量减 1(不管最后已经放到最后的最大值)
    • 对 0 位置进行 1 次 siftDown 操作

堆排序图解


对 {50, 21, 80, 43, 38, 14} 进行原地建堆。

重复执行以下操作,直到堆的元素数量为 1:

  • 交换堆顶元素与尾元素
  • 堆的元素数量减 1
  • 对 0 位置进行 1 次 siftDown 操作





堆排序实现

原地建堆:自下而上的下滤建堆

下滤:其实就是堆删除元素后,恢复堆的性质

完整源码:

/*** 堆排序*/
public class HeapSort<T extends Comparable<T>> extends Sort<T> {private int heapSize; // 堆大小@Overrideprotected void sort() {// 原地建堆(自下而上的下滤)heapSize = array.length;for (int i = (heapSize >> 1) - 1; i >= 0; i--) {siftDown(i);}while (heapSize > 1) {// 交换堆顶元素和尾部元素swap(0, --heapSize);// 对0位置进行siftDown(恢复堆的性质)siftDown(0);}}private void siftDown(int index) {T element = array[index];int half = heapSize >> 1;while (index < half) { // index必须是非叶子节点// 默认是左边跟父节点比int childIndex = (index << 1) + 1;T child = array[childIndex];int rightIndex = childIndex + 1;// 右子节点要存在, 并且比左子节点大if (rightIndex < heapSize && cmp(array[rightIndex], child) > 0) { child = array[childIndex = rightIndex];}// 大于等于子节点if (cmp(element, child) >= 0) break;array[index] = child;index = childIndex;}array[index] = element;}}

生成 20000 个取值在[1, 10000] 的随机数进行排序:

复杂度与稳定性

  • 最好、最坏、平均时间复杂度:O(nlogn)O(nlogn)O(nlogn)
  • 空间复杂度:O(1)O(1)O(1)
  • 堆排序属于不稳定排序

【恋上数据结构】冒泡排序、选择排序、堆排序相关推荐

  1. 【恋上数据结构】计数排序

    计数排序 前言 计数排序-简单实现 实现步骤 代码实现与缺点 计数排序 – 改进 改进-图解 改进-实现 复杂度与稳定性 计数排序-对自定义对象进行排序 经典的十大排序算法! 前言 请务必看一下这个: ...

  2. 【恋上数据结构】希尔排序

    希尔排序 前言 希尔排序思路 实例图解 列的划分思路 步长序列计算代码 希尔排序完整实现 步长序列优化 插入排序优化 复杂度和稳定性 经典的十大排序算法! 前言 请务必看一下这个:排序算法前置知识+代 ...

  3. 堆排序 C++代码实现及思想 排序过程输出 恋上数据结构笔记

    复习梗概 文章目录 复习梗概 什么是堆思想? 堆排序算法怎么来的? 什么是下滤?代码 什么是建堆?代码 堆排序本体 代码及排序过程输出 和时间复杂度 完整代码 什么是堆思想? 最大堆:树形结构,每一个 ...

  4. 数据结构(八):排序 | 插入排序 | 希尔排序 | 冒泡排序 | 快速排序 | 简单选择排序 | 堆排序 | 归并排序 | 基数排序 | 外部排序 | 败者树 | 置换-选择排序 | 最佳归并树

    文章目录 第八章 排序 一.排序的基本概念 (一)什么是排序 (二)排序的应用 (三)排序算法的评价指标 (四)排序算法的分类 (五)总结 二.插入排序 (一)算法思想 (二)算法实现 (三)算法效率 ...

  5. 【恋上数据结构】排序算法前置知识及代码环境准备

    排序准备工作 何为排序? 何为稳定性? 何为原地算法? 时间复杂度的知识 写排序算法前的准备 项目结构 Sort.java Asserts.java Integers.java Times.java ...

  6. 02_Python算法+数据结构笔记-冒泡排序-选择排序-插入排序-快排-二叉树

    b站视频:路飞IT学城 清华计算机博士带你学习Python算法+数据结构_哔哩哔哩_bilibili 文章目录 #11 排序介绍 #12 冒泡排序介绍 #13 冒泡排序 #14 选择排序 #15 插入 ...

  7. 《数据结构与算法》实验:排序算法实验比较——选择排序 堆排序

    <数据结构与算法>实验和课程Github资源 <数据结构与算法>实验:线性结构及其应用--算术表达式求值 <数据结构与算法>实验:树型结构的建立与遍历 <数据 ...

  8. 七大排序算法—图文详解(插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)

    作者:渴望力量的土狗 博客主页:渴望力量的土狗的博客主页 专栏:数据结构与算法 工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器--牛客网 点击免费注册和我一起刷题吧 目录 插入排序: ...

  9. 计数排序及其改进 C++代码实现与分析 恋上数据结构笔记

    文章目录 复习梗概 算法思想 基础思想 改进空间复杂度,改进不能对负数进行排序问题 改进稳定性 计数排序时间空间复杂度 计数排序基础版 代码及输出 计数排序第一次改进版 代码及输出 计数排序终极版 代 ...

  10. 【恋上数据结构与算法 第二季】【04】图-基础实现_遍历_拓扑排序

    持续学习&持续更新中- 学习态度:脚踏实地 [恋上数据结构与算法 第二季][04]图-基础实现_遍历_拓扑排序 图的实现方案 邻接矩阵 邻接表 图的基础接口 顶点.边的定义 图的基础实现 图的 ...

最新文章

  1. php定义常量mypi 3.14,php – Codeigniter 3使用未定义的常量VIEWPATH – 假设’VIEWPATH’...
  2. 算法小论——第三章 又把新桃换旧符
  3. java des验证码,Servlet返回验证码
  4. wps定位对话框快捷键_Word、Excel、PPT快捷键汇总
  5. Spring Boot Actuator
  6. WebGL(五)——WEBGL缓冲区,绘制三角形
  7. 腾讯启动“SaaS技术联盟”联合行业制定互联互通标准
  8. 第三次被盗:Cream Finance 疑存在漏洞,价值1.3亿美元的密币失窃
  9. MySQL的show profile(已过时)简介以及该功能在MySQL 5.7中performance_schema中的替代
  10. c++ map是有序还是无序的_go 学习笔记之数组还是切片都没什么不一样
  11. 面试系列 | 一个线程OOM,进程里其他线程还能运行么?
  12. 计算机基础技能应用查询中心,《计算机基础及技能训练》大纲
  13. 目录操作 递归打印目录 DIR drent
  14. 循序渐进学Docker pdf
  15. idea spring boot 修改html等不重启即时生效
  16. Android 4.4(KitKat)窗口管理子系统 - 体系框架
  17. java邮件附件名称乱码_Java邮件开发(三):解决附件名为乱码及显示友好名称
  18. 关于工资、社保、公积金、个人所得税等小常识
  19. ilove中文_Iloveyou翻译成中文是什么意思
  20. 利用触发器设计计数器

热门文章

  1. 12306外包给阿里巴巴、IBM等大企业做是否可行?
  2. 使用 sync.ErrGroup 实现并发搜索文件
  3. 在编写mini2440 helloworld驱动遇到的问题
  4. sql示例_SQL Server Lead功能概述和示例
  5. sql azure 语法_使用Azure Data Studio从SQL Server数据创建图表
  6. BZOJ4001[TJOI2015]概率论(数学、期望、生成函数、卡特兰数)
  7. poj1833 排列
  8. innerHTML和outerHTML的区别
  9. 线性表顺序表模板 纯本人手工创造
  10. Struts2框架学习(二) Action