常用排序算法(js)

article/2025/11/9 11:34:45

复习排序算法

时间复杂度、空间复杂度、稳定新

排序算法时间复杂度空间复杂度稳定性
冒泡O(n^2)O(1)
选择O(n^2)O(1)不是
插入O(n^2)O(1)
希尔O(nlogn)O(1)不是
快速O(nlogn)O(nlogn)不是
1. 冒泡排序
  • 思路:每一轮都对相邻的两个元素进行比较,如果逆序则交换位置,直到所有元素都排好序为止

  • 基本操作:

  • 代码:

ArrayList.prototype.bubbleSort = () => {const len = this.data.lengthfor (let i = 0; i < len - 1; i++) {for (let j = 0; j < len - 1 - i; j++) {if (this.data[j] > this.data[j + 1]) {const temp = this.data[j]this.data[j] = this.data[j + 1]this.data[j + 1] = temp}}}}
2. 选择排序
  • 思路:每一轮都在待排序的元素中找出最大或最小的值,然后与此次待排序的元素中的第一个进行比较,如果逆序则交换位置;

  • 基本操作:在这里插入图片描述

  • 代码:

  ArrayList.prototype.selectSort = () => {/*** 以从小到大为例* 每一轮都从未排序元素中(不包括第一个)找到最小值与未排序元素的第一个元素进行比较* 符合条件则交换*/const len = this.data.lengthlet min = 0 // 记录最小值的索引for (let i = 0; i < len - 1; i++) {for (let j = i + 1; j < len; j++) {if (this.data[j] < this.data[min]) {min = j}}// 交换const temp = this.data[min]this.data[min] = this.data[i]this.data[i] = temp}}

3. 插入排序
  • 思路:数组可以分为局部有序、局部无序两个部分,每一次都是将一个局部无序的元素按照其大小插入到局部有序序列当中,直到局部无序的元素全部插入为止

  • 基本操作:在这里插入图片描述

  • 代码:

ArrayList.prototype.insertSort = () => {const len = this.data.length//  从第二个元素开始,因为默认以数组第一个元素作为局部有序的一个数列for (let i = 1; i < len; i++) {// 局部排序后面的第一个元素const temp = this.data[i]let j = i//  将 temp 这个元素与局部排序的数列进行比较,然后插入到正确的位置while (j > 0 && this.data[j - 1] > temp) {this.data[j] = this.data[j - 1]j--}this.data[j] = temp// 也可以使用二分法// 使用二分查找法找到需要插入元素的索引号// let r = i - 1// let l = 0// while (l <= r) {//   const middle = Math.floor((l + r) / 2)//   const value = this.data[middle]//   if (value < temp) {//     l = middle + 1//   } else {//     r = middle - 1//   }// }// for (let k = i; k >= l; k--) {//   this.data[k] = this.data[k - 1]// }// this.data[l] = temp}}
4.希尔排序
  • 思路:在直接插入排序方法上改进:引入一个间隔增量(递减,这个增量每次循环都会递减,最小是1)将整个待排序列分割成多个子序列,对每一个子序列都进行直接插入排序,待整个序列基本有序的时候(即间隔增量 === 1),最后对全体元素再进行一次直接插入排序;间隔增量的作用就是将整个序列分割成多个子序列,对每个子序列进行插入排序,这样我们就可以将较小的元素用更少的比较次数就能找到其正确位置

  • 基本操作:在这里插入图片描述
    在这里插入图片描述

  • 代码:

ArrayList.prototype.shellSort = () => {const len = this.data.length//  1. 获取增量let interval = Math.floor(len / 2)//  2. 增量递减while (interval >= 1) {// 3. 使用增量进行分组,开始遍历,执行插入排序// 此时由于引入了增量进行了分组,需要对插入排序进行改造for (let i = interval; i < len; i++) {// 4. 拿到当前元素,去与局部有序的元素进行比较,如果小于局部有序的元素就插入进去,(本例是从小到大排序)const temp = this.data[i]// 5. 记录当前元素的索引号,用于下一个 while 循环(与局部有序的元素进行比较的while循环)let j = i// 6. 当前元素与局部有序元素比较while (temp < this.data[j - interval] && (j - interval) >= 0) {this.data[j] = this.data[j - interval]j -= interval}//  7. 将当前元素插入进去this.data[j] = temp}interval = Math.floor(interval / 2)}
}

5.快速排序
  • 思路:首先取一个元素(一般取数组的第一个元素,或者是挑选数组的第一个元素、中间元素、最后一个元素三个数的中位数)作为 中心;将所有比中心小的元素全部放到中心的左边位置,比中心大的元素全部放到中心的右边位置,以中心元素为界就形成了 两个子序列,然后对每个子序列重新选择中心元素并按照以上规则执行,直到每个子序列的元素只剩下一个
  • 基本操作:在这里插入图片描述

在这里插入图片描述

  • 代码:
ArrayList.prototype.quickSort = () => {const quickSort = (data, left, right) => {// 0. 终止函数执行if (left >= right) return// 1. l,r 为此次排序  子序列的 索引号:l~rlet l = left, r = right//  2. 将第一个元素作为基值(中心值)const ele = data[l]//  3. 循环开始while (l < r) {// 4. 查询是否有小于基值的,获取小于基值的元素的索引号while (data[r] > ele && r > l) { // r > l 这个条件不能少,因为这个while循环会发生 r < l的情况r--}// 5. 查询是否有大于基值的,获取大于基值的元素的索引号while (data[l] <= ele && r > l) { // r > l 这个条件不能少,因为这个while循环会发生 r < l的情况l++}//  6. 跳出两个 while 循环,说明left right 停止移动了,左边遇到大于基值的,右边遇到小于基值的//    交换这两个元素的位置const temp = data[l]data[l] = data[r]data[r] = temp}//  7. 跳出最外层 while 循环,说明 这个基值已经找到了在数组中正确的位置了   将基值放到正确的位置data[left] = data[l]  // 这里要使用left,因为left才是第一个值,经历过while循环后l,r已经变化了,此时 l === rdata[l] = ele//  8. 将基值左右两边的数组序列进行快速排序quickSort(data, left, l - 1)quickSort(data, l + 1, right)}quickSort(this.data, 0, this.data.length - 1)}

ArrayList结构的完整代码

function ArrayList() {this.data = []ArrayList.prototype.insert = (ele) => {this.data.push(ele)}ArrayList.prototype.toString = () => {console.log(this.data.join(' '))return this.data.join(' ')}//  冒泡排序ArrayList.prototype.bubbleSort = () => {/*** 对未排序的各个元素从头到尾依次比较相邻元素的大小关系,符合条件则交换位置,* 外层循环每一次都能找到一个最大值,排放到后面(从小到大)* 以此往复,直到排序已完成*/const len = this.data.lengthfor (let i = 0; i < len - 1; i++) {for (let j = 0; j < len - 1 - i; j++) {if (this.data[j] > this.data[j + 1]) {const temp = this.data[j]this.data[j] = this.data[j + 1]this.data[j + 1] = temp}}}}//   选择排序/*** 基本思想:* 在待排序的元素中找到最大或最小的,放到数组的最前面*/ArrayList.prototype.selectSort = () => {/*** 以从小到大为例* 每一轮都从未排序元素中(不包括第一个)找到最小值与未排序元素的第一个元素进行比较* 符合条件则交换* 相对于冒泡排序,交换次数耗时:O(n)*/const len = this.data.lengthlet min = 0 // 记录最小值的索引for (let i = 0; i < len - 1; i++) {for (let j = i + 1; j < len; j++) {if (this.data[j] < this.data[min]) {min = j}}// 交换const temp = this.data[min]this.data[min] = this.data[i]this.data[i] = temp}}//  插入排序(从小到大)(*)/*** 基本思想:* 每一步将一个待排序的元素,按照其元素大小插入到前面已经排序好的一组元素中,直到元素全部插入为止* 或* 数组可以分为两部分,局部有序,局部无序,每一步将一个局部无序的元素按照其值大小插入到局部有序当中,直到全部元素插入为止*/ArrayList.prototype.insertSort = () => {const len = this.data.length//  从第二个元素开始,因为默认一数组第一个元素作为局部排序的一个数列for (let i = 1; i < len; i++) {// 局部排序后面的第一个元素const temp = this.data[i]// //  将 temp 这个元素与局部排序的数列进行比较,// let j = i// while (j > 0 && this.data[j - 1] > temp) {//   this.data[j] = this.data[j - 1]//   j--// }// this.data[j] = temp//  改进:使用 二分查找法// 二分查找法let r = i - 1let l = 0while (l <= r) {const middle = Math.floor((l + r) / 2)const value = this.data[middle]if (value < temp) {l = middle + 1} else {r = middle - 1}}for (let k = i; k >= l; k--) {this.data[k] = this.data[k - 1]}this.data[l] = temp}}//  希尔排序(**)对插入排序的改进/*** 基本思想:* 引入一个间隔增量(递减),将整个待排序列分割成若干个子序列,分别对每一个进行直接插入排序,* 待整个序列 '基本有序' 的时候(即间隔增量 === 1),最后对全体元素再进行一次直接插入排序*/ArrayList.prototype.shellSort = () => {const len = this.data.length//  1. 获取增量let interval = Math.floor(len / 2)//  2. 增量递减while (interval >= 1) {// 3. 使用增量进行分组,开始遍历,执行插入排序// 此时由于引入了增量进行了分组,需要对插入排序进行改造for (let i = interval; i < len; i++) {// 4. 拿到当前元素,去与局部有序的元素进行比较,如果小于局部有序的元素就插入进去,(本例是从小到大排序)const temp = this.data[i]// 5. 记录当前元素的索引号,用于下一个 while 循环(与局部有序的元素进行比较的while循环)let j = i// 6. 当前元素与局部有序元素比较while (temp < this.data[j - interval] && (j - interval) >= 0) {this.data[j] = this.data[j - interval]j -= interval}//  7. 将当前元素插入进去this.data[j] = temp}interval = Math.floor(interval / 2)}}//  快速排序ArrayList.prototype.quickSort = () => {const quickSort = (data, left, right) => {// 0. 终止函数执行if (left >= right) return// 1. l,r 为此次排序  数组要进行排序的范围: 索引号:l~rlet l = left, r = right//  2. 将第一个元素作为基值const ele = data[l]//  3. 循环开始while (l < r) {// 4. 查询是否有小于基值的,小于基值的放在基值左边while (data[r] > ele && r > l) { // r > l 这个条件不能少,因为这个while循环会发生 r < l的情况r--}// 5. 查询是否有大于基值的,大于基值的放在基值右边while (data[l] <= ele && r > l) { // r > l 这个条件不能少,因为这个while循环会发生 r < l的情况l++}//  6. 跳出两个 while 循环,说明左边遇到大于基值的,右边遇到小于基值的//    交换位置const temp = data[l]data[l] = data[r]data[r] = temp}//  7. 跳出最外层 while 循环,说明 这个基值已经找到了在数组中正确的位置了   将基值放到正确的位置data[left] = data[l]  // 这里要使用left,因为left才是第一个值,经历过while循环后l,r已经变化了,此时 l = rdata[l] = ele//  8. 将基值左右两边的数组序列进行快速排序quickSort(data, left, l - 1)quickSort(data, l + 1, right)}quickSort(this.data, 0, this.data.length - 1)}}const array = new ArrayList()

http://chatgpt.dhexx.cn/article/lWxF3Uea.shtml

相关文章

JS实现快速排序算法

快速排序的基本思想是选择数组中的一个元素作为关键字&#xff0c;通过一趟排序&#xff0c;把待排序的数组分成两个部分&#xff0c;其中左边的部分比所有关键字小&#xff0c;右边的部分比所有关键字大。然后再分别对左右两边的数据作此重复操作&#xff0c;直到所有元素都有…

JavaScript排序算法专栏(JS十大排序算法详解)

一、冒泡排序 1、Explanation And Steps&#xff08;解释的步骤&#xff09; 冒泡排序&#xff08;Bubble Sort&#xff09;也是一种简单直观的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。走访数列的…

JS实现经典的排序算法

几大经典排序算法实现&#xff1a; 1.排序算法介绍&#xff1a; 2.基本算法 2.1 冒泡排序 function bubbleSort(arr) {var len arr.lengthfor (var i 0; i < len; i) {for (var j 0; j < len - 1 - i; j) {if (arr[j] > arr[j 1]) {;[arr[j], arr[j 1]] [arr…

js实现常见排序算法

文章目录 前言一、排序相关概念1.比较排序和非比较排序比较排序非比较排序 2.稳定性和不稳定性 二、各排序算法对比三、排序算法中的通用函数以及对数器1.通用函数交换函数取两索引的中间下标&#xff0c;中间值mid 2.对数器 四、各排序算法的实现1.冒泡排序算法思想过程图解代…

js-常见排序算法

目录 一、选择排序 二、冒泡排序 三、插入排序 1. 希尔排序 四、归并排序 五、快速排序 版权声明&#xff1a;本文为博主原创文章&#xff0c;若文章中有错误请联系博主改正&#xff0c;请不要恶意留言(不喜欢请绕道)。欢迎大家转载&#xff0c;转载时请注明原文地址:https://b…

3.JS排序算法之选择排序

选择排序&#xff08;selectSort&#xff09;&#xff0c;顾名思义&#xff0c;每次选择最值进行排序 目录 一、选择排序算法原理 二、选择排序算法分析 三、选择排序算法应用实例 四、选择排序的适用场景 一、选择排序算法原理 1.思路 选择排序的实现思路是从未排序序列中…

JavaScript实现十大排序算法(图文详解)

冒泡排序 排序的效果图 解法 当前解法为升序 冒泡排序的特点&#xff0c;是一个个数进行处理。第i个数&#xff0c;需要与后续的len-i-1个数进行逐个比较。 为什么是 len-i-1个数&#xff1f; 因为数组末尾的i个数&#xff0c;已经是排好序的&#xff0c;确认位置不变的了。…

JS 常见的排序算法

工作中算法不常用&#xff0c;但是排序经常用。因此在这里整理了几种JS中常见的排序算法。 冒泡排序 1、算法思想&#xff1a;判断两个相邻元素&#xff0c;大于则交换位置 2、算法步骤 从数组中第一个数开始&#xff0c;依次与下一个数比较并次交换比自己小的数&#xff0c…

详细解析十大排序算法(js实现)

详细解析十大排序算法js实现 算法概述1.冒泡排序1.1算法描述1.2动图演示1.3代码实现 2.选择排序2.1算法描述2.2动图演示2.3代码实现2.4算法分析 3.插入排序3.1算法描述3.2动图演示3.3代码实现3.4算法分析 4.希尔排序4.1算法描述4.2动图演示4.3代码实现4.4算法分析 5.归并排序5.…

Excel中使用SUMIFS公式时计算结果不正确(原因:有超过15位数字的长编码)

在使用SUMIFS公式进行多条件求和时发现求和结果部分正确&#xff0c;部分错误。 常见原因&#xff1a; 1、公式错误 2、数据格式有问题或者有空格等 仔细检查后发现并不是上述两个原因&#xff0c;而是求和的公式中涉及到超过15位数字的长编码。常见的SUMIF、SUMIFS、COUNTIF等…

mybatis-plus使用

1 mybaitsplus简介 &#xff08;1&#xff09;对于mybatis功能的增强&#xff0c;具体的体现就是对于单表的操作都生成好了&#xff0c;分页&#xff0c;条件查询使用很方便&#xff0c;例如查询操作&#xff0c;直接使用wrapper的实现类&#xff0c;调用方法进行条件的增加&a…

四、Hibernate框架的API (三)-- Session对象

一、Session对象 1.Hibernate最重要的对象,只用使用hibernate与数据库操作&#xff0c;都用到这个对象2.该对象维护了一个Connection对象。代表了与数据库连接的会话。3.该对象实质上是对Connection对象的包装&#xff0c;在Connection对象基础之上&#xff0c;封装了一些方法。…

Criteria的用法

一、Hibernate提供了5种检索对象的方式 1.导航对象图检索方式&#xff1a;根据已经加载的对象导航到其他对象    from Emp e group by e.dept.deptName 2.OID检索方式&#xff1a;按照对象的OID来检索对象   get/load 3.HQL检索方式&#xff1a;使用面向对象的HQL查询语…

第13章:处理Excel电子表格(笔记)

13.1&#xff1a;Excel文档 13.2&#xff1a;安装openpyxl模块 pip install --user --Uopenpuxl2.6.2 这是安装2.6.2版本的&#xff0c;比较新的版本与学习的书籍的信息有一点不兼容 13.3&#xff1a;读取Excel文档 13.3.1&#xff1a;用openpyxl模块打开Excel文档 import …

关于 range.autofilter 和 VBA的 filter

1 range().autofilter容易出错的地方 1.1 range().autofilter的返回值 range().autofilter 返回值总是 true返回值并不是对象&#xff0c;而是执行一个筛选的操作所以 Sub test1_filter5() Dim rng1 As Range Set rng1 Range("b1:b20").AutoFilter(field:1, Crit…

Opencv学习之角点检测

Opencv学习之角点检测 角点检测 在图像处理和计算机视觉领域&#xff0c;兴趣点&#xff08;interest points&#xff09;&#xff0c;也被称作关键点&#xff08;key points&#xff09;、特征点&#xff08;feture points&#xff09;。它被大量用于解决物体识别、图像识别…

VBA-Range.AutoFilter 方法浅析

VBA-Range.AutoFilter 方法的一些“坑” 学到筛选的时候遇到一些小小的“坑”&#xff0c;记录下。 录制出来的宏是这样的&#xff0c; Sub 宏1()宏1 宏Rows("1:1").SelectSelection.AutoFilterActiveSheet.Range("$A$1:$F$1048").AutoFilter field:4, …

Hibernate查询Query By Criterial

提供的检索方式&#xff1a;&#xff08;1&#xff09;导航对象图检索方式 &#xff08;2&#xff09;OID检索方式&#xff08;3&#xff09;HQL检索方式&#xff08;4&#xff09;QBC检索方式[query by Criteria(标准)]&#xff08;5&#xff09;本地SQL检索方式 1、简介 1.…

SLUB和SLAB的区别

转载&#xff1a;http://www.cnblogs.com/tolimit/ 首先为什么要说slub分配器&#xff0c;内核里小内存分配一共有三种&#xff0c;SLAB/SLUB/SLOB&#xff0c;slub分配器是slab分配器的进化版&#xff0c;而slob是一种精简的小内存分配算法&#xff0c;主要用于嵌入式系统。慢…

[linux kernel]slub内存管理分析(7) MEMCG的影响与绕过

文章目录 背景前情回顾描述方法约定 MEMCG总览省流总结简介 slub 相关 memcg机制kernel 5.9 版本之前结构体初始化具体实现 kernel 5.9-5.14kernel 5.14 之后 突破slab限制方法cross cache attackpage 堆风水 总结 背景 前情回顾 关于slab几个结构体的关系和初始化和内存分配…