当前位置: 首页 > news >正文

各种排序方法总结

目录

1. 冒泡排序 (Bubble Sort

2. 选择排序 (Selection Sort)

3. 插入排序 (Insertion Sort)

4. 快速排序 (Quick Sort)

5. 归并排序 (Merge Sort)

6. 堆排序 (Heap Sort)


排序算法 时间复杂度 空间复杂度 备注
冒泡排序 最好情况: O(n)
平均情况: O(n^2)
最坏情况: O(n^2)
 O(1)  原地排序,只需常量级额外空间
选择排序

最好情况: O(n^2)

平均情况: O(n^2)
最坏情况: O(n^2)

 O(1) 原地排序,只需常量级额外空间
插入排序最好情况: O(n)
平均情况: O(n^2)
最坏情况: O(n^2)
 O(1) 原地排序,只需常量级额外空间
快速排序最好情况: O(n log n)
平均情况: O(n log n)
最坏情况: O(n^2
O(log n) 递归调用栈空间,最好情况O(log n),最坏情况O(n),但平均情况为O(log n)
归并排序最好情况:O(n log n)
平均情况: O(n log n)
最坏情况: O(n log n)
 O(n)  需要额外的临时数组来存储合并结果
堆排序最好情况: O(n log n)
平均情况: O(n log n)
最坏情况: O(n log n)
O(1)  原地排序,堆的调整过程在数组内部进行,只需常量级额外空间(不考虑递归实现,若考虑递归则与快速排序类似)

1. 冒泡排序 (Bubble Sort

时间复杂度:

  • 最好情况: O(n)
  • 平均情况: O(n^2)
  • 最坏情况: O(n^2)
function bubbleSort(arr) {  let n = arr.length;  for (let i = 0; i < n - 1; i++) {  for (let j = 0; j < n - 1 - i; j++) {  if (arr[j] > arr[j + 1]) {  // 交换元素  [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];  }  }  }  return arr;  
}

2. 选择排序 (Selection Sort)

原理:

选择排序是一种简单直观的排序算法。它的工作原理是首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

具体步骤如下:

  1. 从未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置。
  2. 再从剩余未排序元素中继续寻找最小(或最大)元素,放到已排序序列的末尾。
  3. 重复第二步,直到所有元素均排序完毕。

特点:

  • 选择排序的时间复杂度为O(n^2),其中n是待排序元素的数量。
  • 选择排序是一种原地排序算法,因为它只需要一个额外的空间来存储当前找到的最小(或最大)元素。
  • 选择排序不是稳定的排序算法,因为相同元素的相对位置可能会在排序过程中发生改变。

时间复杂度:

  • 最好情况: O(n^2)
  • 平均情况: O(n^2)
  • 最坏情况: O(n^2)
function selectionSort(arr) {  let n = arr.length;  for (let i = 0; i < n - 1; i++) {  let minIndex = i;  for (let j = i + 1; j < n; j++) {  if (arr[j] < arr[minIndex]) {  minIndex = j;  }  }  // 交换元素  [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];  }  return arr;  
}

3. 插入排序 (Insertion Sort)

原理:

插入排序的工作方式是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,找到相应位置并插入时,不需要移动元素,只需将要插入的元素移动到插入点即可。

具体步骤如下:

  1. 从第一个元素开始,该元素可以认为已经被排序。
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描。
  3. 如果该元素(已排序)大于新元素,则将该元素移到下一位置。
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。
  5. 将新元素插入到该位置后。
  6. 重复步骤2~5,直到所有元素均排序完毕。

特点:

  • 插入排序的时间复杂度为O(n^2),在数据规模较小时表现良好,特别是当数据基本有序时,时间复杂度可以接近O(n)。
  • 插入排序是一种原地排序算法,因为它只需要一个额外的空间来存储当前正在插入的元素。
  • 插入排序是稳定的排序算法,因为相同元素的相对位置在排序过程中不会发生改变。

时间复杂度:

  • 最好情况: O(n)
  • 平均情况: O(n^2)
  • 最坏情况: O(n^2)
function insertionSort(arr) {  let n = arr.length;  for (let i = 1; i < n; i++) {  let key = arr[i];  let j = i - 1;  while (j >= 0 && arr[j] > key) {  arr[j + 1] = arr[j];  j = j - 1;  }  arr[j + 1] = key;  }  return arr;  
}

4. 快速排序 (Quick Sort)

原理:

快速排序是一种通过基准划分区块,再不断交换左右项的排序方式。它采用了分治法,减少了交换的次数。快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归或迭代进行,以此让整个数列变成有序序列。

具体步骤如下:

  1. 在待排序区间找到一个基准点(pivot),一般选择数组的第一个元素、最后一个元素或者随机选择一个元素。
  2. 逐个循环数组,将小于基准的项放在左侧,将大于基准的项放在右侧。一般通过交换的方式来实现。
  3. 对基准点左侧全部项和基点右侧全部项分别通过递归(或迭代)方式重复上述步骤,直到所有数组都交换完成。

时间复杂度:

  • 最好情况: O(n log n)
  • 平均情况: O(n log n)
  • 最坏情况: O(n^2) (但可以通过随机化选择基准元素等方法优化)
function quickSort(arr) {  if (arr.length <= 1) {  return arr;  }  let pivot = arr[Math.floor(arr.length / 2)];  let left = [];  let right = [];  for (let i = 0; i < arr.length; i++) {  if (i === Math.floor(arr.length / 2)) continue;  if (arr[i] < pivot) {  left.push(arr[i]);  } else {  right.push(arr[i]);  }  }  return [...quickSort(left), pivot, ...quickSort(right)];  
}

5. 归并排序 (Merge Sort)

原理:

归并排序是一种分治算法,其工作原理是将未排序的列表划分为n个子列表,每个子列表包含一个元素(包含一个元素的列表被认为是有序的),然后重复合并子列表以生成新的有序子列表,直到只剩下一个子列表。
具体步骤如下:

  1. 分解:将待排序的n个元素的序列分成两个子序列,每个子序列包含n/2个元素。
  2. 解决:使用归并排序递归地排序两个子序列。
  3. 合并:将两个已排序的子序列合并成一个最终的排序序列。

时间复杂度:

  • 最好情况: O(n log n)
  • 平均情况: O(n log n)
  • 最坏情况: O(n log n)
function mergeSort(arr) {  if (arr.length <= 1) {  return arr;  }  const middle = Math.floor(arr.length / 2);  const left = arr.slice(0, middle);  const right = arr.slice(middle);  return merge(mergeSort(left), mergeSort(right));  
}  function merge(left, right) {  let result = [];  let leftIndex = 0;  let rightIndex = 0;  while (leftIndex < left.length && rightIndex < right.length) {  if (left[leftIndex] < right[rightIndex]) {  result.push(left[leftIndex]);  leftIndex++;  } else {  result.push(right[rightIndex]);  rightIndex++;  }  }  return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));  
}

6. 堆排序 (Heap Sort)

堆排序(Heap Sort)是一种基于堆(Heap)这种数据结构的比较排序算法。堆是一个近似完全二叉树的结构,分为最大堆(Max Heap)和最小堆(Min Heap)。在最大堆中,每个节点的值都大于或等于其子节点的值;在最小堆中,每个节点的值都小于或等于其子节点的值。堆排序通常使用最大堆来实现升序排序

堆排序原理:

  1. 构建最大堆:
  • 将数组看作一个完全二叉树,构建最大堆。
  • 从最后一个非叶子节点开始,向上依次调整堆,使得每个子树都满足最大堆的性质。

     2.堆排序过程:

  • 将堆顶元素(最大值)与堆的最后一个元素交换。
  • 堆的大小减1,重新调整堆顶元素所在的子树,使其满足最大堆的性质。
  • 重复上述步骤,直到堆的大小为1。

时间复杂度:

  • 最好情况: O(n log n)
  • 平均情况: O(n log n)
  • 最坏情况: O(n log n)
function heapSort(arr) {  let n = arr.length;  // 构建最大堆  for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {  heapify(arr, n, i);  }  // 一个个从堆顶取出元素  for (let i = n - 1; i > 0; i--) {  // 交换当前堆顶(最大值)和最后一个元素  [arr[0], arr[i]] = [arr[i], arr[0]];  // 重新调整堆  heapify(arr, i, 0);  }  return arr;  
}  function heapify(arr, n, i) {  let largest = i;  //最大子节点let left = 2 * i + 1;  //左子节点let right = 2 * i + 2;  //右子节点//如果左子节点存在且大于当前最大子节点if (left < n && arr[left] > arr[largest]) {  largest = left;  }  //如果右子节点存在且大于当前最大子节点if (right < n && arr[right] > arr[largest]) {  largest = right;  }  //如果最大值不是当前子节点,则交换 if (largest !== i) {  [arr[i], arr[largest]] = [arr[largest], arr[i]];  heapify(arr, n, largest);  }  
}

相关文章:

各种排序方法总结

目录 1. 冒泡排序 (Bubble Sort 2. 选择排序 (Selection Sort) 3. 插入排序 (Insertion Sort) 4. 快速排序 (Quick Sort) 5. 归并排序 (Merge Sort) 6. 堆排序 (Heap Sort) 排序算法 时间复杂度 空间复杂度 备注冒泡排序 最好情况: O(n) 平均情况: O(n^2) 最坏情况: O(n^…...

【工欲善其事】巧用 PowerShell 自动清除复制 PDF 文本时夹杂的换行符号

文章目录 巧用 PowerShell 自动清除复制 PDF 文本时夹杂的换行符号1 问题描述2 解决方案3 具体步骤4 效果测试5 小结与复盘 巧用 PowerShell 自动清除复制 PDF 文本时夹杂的换行符号 1 问题描述 不知各位是否也为复制过来的文本中夹杂的回车换行符抓狂过&#xff1f;就是在复…...

Maven与Gradle的区别

Maven与Gradle是两种流行的构建工具&#xff0c;广泛用于Java项目的管理和构建。以下是它们的对比&#xff0c;包括官网、Windows 11配置环境、在IDEA中的相同点和不同点&#xff0c;以及它们各自的优缺点。 官网 Maven官网: https://maven.apache.orgGradle官网: https://gr…...

【linux 多进程并发】0202 Linux进程fork之后父子进程间的文件操作有着相同的偏移记录,多进程操作文件的方法

0202 Linux进程资源 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 020…...

SQLite在安卓中的应用

在 Android 应用程序中&#xff0c;SQLite 是默认的嵌入式数据库解决方案&#xff0c;Android 系统为开发者提供了相应的 API 来管理 SQLite 数据库。通过使用 SQLiteOpenHelper 类和 SQLiteDatabase 类&#xff0c;开发者可以方便地创建、查询、更新和删除数据库中的数据。 以…...

Python数据库操作

前面的章节中学习了使用 Python 读写文件的方法&#xff0c;大家可以用文件方式来存放数据&#xff0c;不过使用文件方式时不容易管理&#xff0c;同时还容易丢失&#xff0c;会带来许多问题。目前主流的方法都是采用数据库软件&#xff0c;通过数据库软件来组织和存放数据&…...

交叉熵损失函数为代表的两层神经网络的反向传播量化求导计算公式

反向传播&#xff08;back propagation&#xff0c;BP&#xff09;算法也称误差逆传播&#xff0c;是神经网络训练的核心算法。我们通常说的 BP 神经网络是指应用反向传播算法进行训练的神经网络模型。反向传播算法的工作机制究竟是怎样的呢&#xff1f;我们以一个两层&#xf…...

数据结构——八大排序(上)

数据结构中的八大排序算法是计算机科学领域经典的排序方法&#xff0c;它们各自具有不同的特点和适用场景。以下是这八大排序算法的详细介绍&#xff1a; 一、插入排序&#xff08;Insertion Sort&#xff09; 核心思想&#xff1a;将数组中的所有元素依次跟前面已经排好的元…...

vxe-table 导入导出功能全解析

一、vxe-table 导入导出功能概述 vxe-table 的导入导出功能在数据处理中具有至关重要的作用。在现代数据管理和处理的场景中&#xff0c;高效地导入和导出数据是提高工作效率的关键。 对于导入功能而言&#xff0c;它允许用户将外部的表格数据&#xff0c;如 Excel 文件&…...

常用STL的操作以及特点

C 标准模板库&#xff08;STL&#xff09;提供了很多常用的数据结构和算法&#xff0c;极大简化了开发工作。STL 包括容器&#xff08;如 vector、list、map 等&#xff09;、算法&#xff08;如排序、查找等&#xff09;以及迭代器。以下是一些常用 STL 容器的操作以及它们的特…...

025 elasticsearch索引管理-Java原生客户端

文章目录 pom.xml1创建索引2.创建索引并设置settings信息3.创建索引并设置mapping信息4.删除索引库5.给未设置mapping的索引设置mapping elasticsearch版本7.10.2&#xff0c;要求java客户端与之相匹配&#xff0c;推荐Springboot版本是2.3以上版本 依赖配置使用的是JUnit 5&am…...

Gin框架操作指南10:服务器与高级功能

官方文档地址&#xff08;中文&#xff09;&#xff1a;https://gin-gonic.com/zh-cn/docs/ 注&#xff1a;本教程采用工作区机制&#xff0c;所以一个项目下载了Gin框架&#xff0c;其余项目就无需重复下载&#xff0c;想了解的读者可阅读第一节&#xff1a;Gin操作指南&#…...

AIGC技术的学习 系列一

文章目录 前言一、AIGC技术演进1.1 图像视频生成1.2. 文本生成1.3. 多模态生成1.4. 小结二、CAD&CAE软件介绍2.1. CAD软件2.2. CAE软件2.3. 小结三、AIGC技术与CAD&CAE软件的集成案例3.1. 土建设计领域3.2. 机械设计领域四、结语五、参考文献总结前言 在全球智能制造的…...

Milvus×Dify半小时轻松构建RAG系统

最近&#xff0c;检索增强生成&#xff08;RAG&#xff09;技术在AI界引起了广泛关注。作为一种将知识库与生成模型结合的新型架构&#xff0c;RAG大大提升了AI应用的实际表现。而在构建RAG系统时&#xff0c;Milvus作为业界领先的开源向量数据库&#xff0c;扮演着关键角色。本…...

wireshark 解密浏览器https数据包

一、导出浏览器证书有两种方法 1、在浏览器快捷方式追加启动参数&#xff1a; --ssl-key-log-file"d:\log\2.log" C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe --ssl-key-log-file"d:\log\2.log" 2、环境变量中新建用…...

【HTML】构建网页的基石

我的主页&#xff1a;2的n次方_ HTML 是一种超文本标记语言&#xff0c;不仅有文本&#xff0c;还能包含图片&#xff0c;音频等 1. HTML 的文件基本结构 html 标签是整个 html 文件的最顶层标签&#xff0c;head 标签中写页面的属性&#xff0c;body 标签是页面中显示的…...

rust不允许在全局区定义普通变量!

文章目录 C 中的全局变量Rust 中的全局变量设计哲学的体现 在 C 和 Rust 中&#xff0c;全局变量的处理方式体现了这两种语言设计哲学上的一些根本性差异&#xff1a; C 中的全局变量 C 允许在全局作用域中定义变量。这些变量在程序的整个生命周期内都存在&#xff0c;从程序开…...

量化投资中的数据驱动决策:大数据如何改变金融市场

随着科技的进步&#xff0c;金融行业迎来了前所未有的变革&#xff0c;量化投资作为其中的代表&#xff0c;逐渐成为投资市场的主流。量化投资是基于数学模型、数据分析以及算法策略的投资方式&#xff0c;与传统依赖经验和直觉的投资方法相比&#xff0c;它的核心优势在于能够…...

MySQL 设计数据表

一个数据表主要包含信息有 : 表名、主键、字段、数据类型、索引&#xff0c;本节主要介绍表的命名规范、字段命名、字段的数据类型选择。 新建的表都是新建在 “item_name” 数据库中的&#xff0c;新建 “item_name” 数据库命令如下 : CREATE DATABASE item_name;新建数据库…...

【大数据技术基础 | 实验一】配置SSH免密登录

文章目录 一、实验目的二、实验要求三、实验原理&#xff08;一&#xff09;大数据实验一体机&#xff08;二&#xff09;SSH免密认证 四、实验环境五、实验内容和步骤&#xff08;一&#xff09;搭建集群服务器&#xff08;二&#xff09;添加域名映射&#xff08;三&#xff…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...