十大排序总结(js实现、稳定性、内外部排序区别、时间空间复杂度、冒泡、快速、直接选择、堆、直接插入、希尔、桶、基数、归并、计数排序)

目录

排序相关概念

稳定性

 内部排序

外部排序

 十种排序算法特点总结

交换排序

冒泡排序(数组sort方法的原理)

图解

 js实现

特点

快速排序

图解

js实现

特点

选择排序

直接选择排序

图解

 js实现

特点

堆排序

大(小)顶堆

非叶节点

js实现 

特点

插入排序 

直接插入排序

图解

js实现 

特点

希尔排序

图解

js实现

特点

其它排序

桶排序

图解

js实现

特点

基数排序

图解

js实现

特点

归并排序

图解

 js实现

特点

计数排序

图解

 js实现

特点



排序相关概念


稳定性

不改变相同数值的顺序为稳定。例如在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的(记录的相对次序保持不变);否则称为不稳定的。


 内部排序

指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列。有冒泡、选择、插入、希尔、快速、堆排序(通常快速排序为最好的)


外部排序

外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。有归并、计数、桶、基数排序


 十种排序算法特点总结


交换排序


冒泡排序(数组sort方法的原理)

1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

3.针对所有的元素重复以上的步骤,除了最后一个。

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。


图解


 js实现

function swap(arr, x, y) {let tmp = arr[x]arr[x] = arr[y]arr[y] = tmp
}
function bubbleSort(arr) {let len = arr.length;for (let i = 0; i < len - 1; i++) {//比较出一轮中的最大值放入最后for (let j = 0; j < len - 1 - i; j++) {if (arr[j] > arr[j + 1]) {swap(arr, j, j + 1)}}}return arr;
}


特点

  1. 时间复杂度:O(N^2)
  2. 空间复杂度:O(1)
  3. 稳定性:稳定


快速排序

1.以数组第一位为基准值,将小于的元素放在左边,大于的元素放在右边,分为左右两块。

2.在左右2块中重复第一步,不断循环,直到分区的大小为1则停止。


图解

注意左右分区,我们可以通过将基准元素和左边分区最右端元素交换实现


js实现

function swap(arr, x, y) {let tmp = arr[x]arr[x] = arr[y]arr[y] = tmp
}
//用于一次以基准值进行排序
function partition(arr, left, right) {//设定基准值pivotlet pivot = leftlet index = pivot + 1for (let i = index; i <= right; i++) {//小于基准值的放左边,大于的不变if (arr[i] < arr[pivot]) {swap(arr, i, index)index++}}//和小于基准值的最右边一个交换位置,实现左边小于基准值,右边大于基准值swap(arr, pivot, index - 1)//返回基准值的位置return index - 1
}
function quickSort(arr, left, right) {let len = arr.lengthleft = typeof left != 'number' ? 0 : leftright = typeof right != 'number' ? len - 1 : rightif (left < right) {//进行一次排序let partitionIndex = partition(arr, left, right)//递归对左边进行排序quickSort(arr, left, partitionIndex - 1)//递归对右边进行排序quickSort(arr, partitionIndex + 1, right)}return arr
}
console.log(quickSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5]))


特点

  1. 时间复杂度:O(N*logN)
  2. 空间复杂度:O(logN)
  3. 稳定性:不稳定


选择排序



直接选择排序

每一次遍历待排序的数据元素从中选出最小(或最大)的一个元素,存放在序列的起始(或者末尾)位置(和原存放位置上的元素交换顺序),直到全部待排序的数据元素排完。


图解


 js实现

//交换数组下标x位和y位的元素
function swap(arr, x, y) {arr[x] = arr[x] - arr[y]arr[y] = arr[y] + arr[x]arr[x] = arr[y] - arr[x]return arr
}
function selectionSort(arr) {let t = arr.lengthlet x = 0while (x != t) {let min = 0;let tmp = Number.MAX_VALUE//选出最小的元素的下标for (let i = x; i < t; i++) {if (tmp > arr[i]) {tmp = arr[i]min = i}}//不是当前位置,则交换顺序if (x != min) {swap(arr, x, min)}x++}return arr
}
console.log(selectionSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5]))


特点

  1. 时间复杂度:O(N^2)
  2. 空间复杂度:O(1)
  3. 稳定性:不稳定


堆排序

1.将元素排序为一个大(小)顶堆,则顶部元素为最大(小)元素,将其与元素尾(头)部元素交换顺序。

2.重新排序剩下元素,再次形成大(小)顶堆,重复1操作,直到只剩一个元素。


大(小)顶堆

每个节点的值都大于(小于)或等于其子节点的值,在堆排序算法中用于升(降)序排列;

代码中表示为:

大顶堆arr[i]>=arr[2i+1]和arr[i]>=arr[2i+2]        父节点大于左右子节点

小顶堆arr[i]<=arr[2i+1]和arr[i]<=arr[2i+2]         父节点小于左右子节点


非叶节点

有孩子节点的节点。最后一个非叶节点在数组中的序号为元素个数除以2向下取整。


js实现 

// 建立大顶堆
function buildMaxHeap(arr) {let len = arr.length;//Math.floor(len/2)表示最后一个非叶节点(含有子节点的节点),//从后往前调整每一个非叶子节点的顺序,使堆变为大顶堆for (let i = Math.floor(len / 2); i >= 0; i--) {heapify(arr, i, len);}
}
// 调整堆
function heapify(arr, i, len) {let left = 2 * i + 1,right = 2 * i + 2,largest = i;//通过2次判断选出父节点和2个子节点中最大的一个if (left < len && arr[left] > arr[largest]) {largest = left;}if (right < len && arr[right] > arr[largest]) {largest = right;}//将最大的节点和父节点交换顺序if (largest != i) {swap(arr, i, largest);//递归对换顺序的节点进行调整,使其还是大顶堆heapify(arr, largest, len);}
}
function swap(arr, i, j) {var temp = arr[i];arr[i] = arr[j];arr[j] = temp;
}
function heapSort(arr) {// 建立大顶堆buildMaxHeap(arr);let len = arr.length//每次建立一个大顶堆,将最大的元素(堆顶元素)放入尾部达到排序效果for (let i = len - 1; i > 0; i--) {swap(arr, 0, i);len--;heapify(arr, 0, len);}return arr;
}
console.log(heapSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5]))


特点

  1. 时间复杂度:O(N*logN)
  2. 空间复杂度:O(1)
  3. 稳定性:不稳定


插入排序 


直接插入排序

每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序(默认是从后向前比较)。


图解

蓝色部分为无序表,黄色部分为有序表:

在这里插入图片描述


js实现 

使用的是一个数组,将数组下标为i之前的为有序,之后为无序。

 注意用的是改变原数组的方法,可以不用返回。

//将数组下标为的x元素取出插入为y的
function popInsert(arr,x,y){arr.splice(y,0,...arr.splice(x,1))
}
function insertSort(arr){let t=arr.lengthfor (let i=1;i<t;i++){let j=i-1do{if(arr[j]<arr[i]){popInsert(arr,i,j+1)break}j--//比较到下标为0的时候直接插入if(j<0){popInsert(arr,i,0)}}while(j>=0)}return arr
}
console.log(insertSort([3,1,2,3134,113,342,123412,55,111,4,234,5,5]))


特点

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定


希尔排序

希尔排序在直接排序之前,进行预排列,将某些极端数据更快的排列到数列前面,构成一个接近排列好的序列,最后再进行一次直接插入排序。

预排列的原理也是插入排列,只不过这里的将数组分成了gap组,分别对每一个小组进行插入排序。


图解

对于升序,当gap从5 – 2 – 1的过程中,排在后面的数值小的数能更快排到前面,当gap为1的时候实际上就是进行了一次插入排序


在这里插入图片描述


js实现

每次将下标位置差为gap的数进行直接排序,其中第一次gap=Math.floor(arr.length/2),之后每次gap=Math.floor(gap/2)。

function shellsSort(arr){let t=arr.lengthlet gap=tlet tmp//gap取不同值的排序do{//每次的分组gap=Math.floor(gap/2)for(let i=gap;i<t;i++){//只和上一个间距为gap的元素进行比较,判断是否要插入,还是维持原顺序if(arr[i-gap]>arr[i]){tmp = arr[i]let j=i-gap//将插入位置之后的元素整体后移do{arr[j+gap]=arr[j]j-=gap}while(j>=0&&arr[j]>tmp)//插入对应位置arr[j+gap]=tmp}}}while(gap>1)return arr
}
console.log(shellsSort([3,1,2,3134,113,342,123412,55,111,4,234,5,5]))


特点

  1. 希尔排序是对直接插入排序的优化当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比
  2. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,一般来说为O(n^1.3) 
  3. 稳定性:不稳定


其它排序


桶排序

选出待排序元素中的最大最小值,根据最大最小值划分多个区域(桶),通过映射函数将元素分到不同区域(桶)中,对区域(桶)中的元素进行排序后,依次取出即可。


图解

将排序的元素放入对应的桶中

 对桶中的元素进行排序


js实现

//插入排序
function insertionSort(arr) {let len = arr.length;let preIndex, current;for (let i = 1; i < len; i++) {preIndex = i - 1;current = arr[i];while (preIndex >= 0 && arr[preIndex] > current) {arr[preIndex + 1] = arr[preIndex];preIndex--;}arr[preIndex + 1] = current;}return arr;
}
function bucketSort(arr, bucketSize) {let minValue = arr[0];let maxValue = arr[0];//找到数组中的最大和最小值for (let i = 1; i < arr.length; i++) {if (arr[i] < minValue) {minValue = arr[i];} else if (arr[i] > maxValue) {maxValue = arr[i];}}//桶的初始化let DEFAULT_BUCKET_SIZE = 5;// 设置一个桶能存储的默认数量为5bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;//桶的个数let bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;let buckets = new Array(bucketCount);for (let i = 0; i < buckets.length; i++) {buckets[i] = [];}//利用映射函数将元素分配到各个桶中for (let i = 0; i < arr.length; i++) {buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);}//删除arr数组中的所有元素arr.length = 0;for (let i = 0; i < buckets.length; i++) {// 对每个桶进行排序,这里使用了插入排序insertionSort(buckets[i]);// 将每个桶的数据从小到大拿出                    for (let j = 0; j < buckets[i].length; j++) {arr.push(buckets[i][j]);}}return arr;
}
console.log(bucketSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5]))


特点

  1. 时间复杂度:O(N+K)
  2. 空间复杂度:O(N+K)
  3. 稳定性:稳定


基数排序

确定最大数的位数,先按第一位进行排序,在按第二位进行排序,直到按最后一位进行排序为止。


图解


js实现

function radixSort(arr) {let counter = [];//获取元素的最大位数let maxDigit = `${Math.max(...arr)}`.lengthlet mod = 10;let dev = 1;//从小到大依次对元素的每一位进行循环排序for (let i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {for (let j = 0; j < arr.length; j++) {//获取元素对应位上的数值let bucket = parseInt((arr[j] % mod) / dev);if (counter[bucket] == null) {counter[bucket] = [];}//根据对应的数值,将元素放入对应的桶中counter[bucket].push(arr[j]);}let pos = 0;//从0~9的桶中将元素取出,完成一次排序for (let j = 0; j < counter.length; j++) {let value = null;if (counter[j] != null) {while ((value = counter[j].shift()) != null) {arr[pos++] = value;}}}}return arr;
}
console.log(radixSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5], 6))


特点

  1. 时间复杂度:O(N*K)
  2. 空间复杂度:O(N+K)
  3. 稳定性:稳定


归并排序

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

  4. 重复步骤 3 直到某一指针达到序列尾;

  5. 将另一序列剩下的所有元素直接复制到合并序列尾。


图解


 js实现

function mergeSort(arr) {  // 采用自上而下的递归方法let len = arr.length;if (len < 2) {return arr;}let middle = Math.floor(len / 2),left = arr.slice(0, middle),right = arr.slice(middle);return merge(mergeSort(left), mergeSort(right));
}
function merge(left, right) {let result = [];while (left.length && right.length) {if (left[0] <= right[0]) {result.push(left.shift());} else {result.push(right.shift());}}while (left.length)result.push(left.shift());while (right.length)result.push(right.shift());return result;
}
console.log(mergeSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5], 6))


特点

  1. 时间复杂度:O(N*logN)
  2. 空间复杂度:O(N)
  3. 稳定性:稳定


计数排序

1.找出待排序的数组中最大和最小的元素

2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项

3.对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)

4.反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1


图解


 js实现

function countingSort(arr) {let maxValue = Math.max(...arr)let bucket = new Array(maxValue + 1),sortedIndex = 0;arrLen = arr.length,bucketLen = maxValue + 1;for (let i = 0; i < arrLen; i++) {if (!bucket[arr[i]]) {bucket[arr[i]] = 0;}bucket[arr[i]]++;}for (let j = 0; j < bucketLen; j++) {while (bucket[j] > 0) {arr[sortedIndex++] = j;bucket[j]--;}}return arr;
}
console.log(countingSort([3, 1, 2, 3134, 113, 342, 123412, 55, 111, 4, 234, 5, 5]))


特点

  1. 时间复杂度:O(N+K)
  2. 空间复杂度:O(K)
  3. 稳定性:稳定


---------------------
作者:YF-SOD
来源:CSDN
原文:https://blog.csdn.net/AIWWY/article/details/121346132
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

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

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

相关文章

三维重建技术概述

基于视觉的三维重建&#xff0c;指的是通过摄像机获取场景物体的数据图像&#xff0c;并对此图像进行分析处理&#xff0c;再结合计算机视觉知识推导出现实环境中物体的三维信息。 1. 相关概念 &#xff08;1&#xff09;彩色图像与深度图像 彩色图像也叫作RGB图像&#xff0c;…

【ArcGIS微课1000例】0032:ArcGIS中河流(曲线)、湖泊(水体色)图例制作案例教程

河流作为线要素,在符号化的过程中使用的大多都是直线符号,但是为了能够在出图的使用表现形象的河流对象,就有了使用曲线表示河流图例的需求,湖泊亦是如此。本文讲解在ArcGIS中制作标准的河流和湖泊图例的完整教程。 文章目录 一、案例效果二、图例制作三、图例修改一、案例…

浅谈微信小程序对于房地产行业的影响

前几日&#xff0c;我们曾经整理过一篇文章是关于微信小程序对于在线旅游业的影响的一些反思&#xff08;浅谈微信小程序对OTA在线旅游市场的影响&#xff09;&#xff0c;近日由于生活工作的需要走访了一些房地产的住宅商品房&#xff0c;突然想到微信小程序对于房地产行业会有…

新型基础测绘与实景三维中国建设技术文件【1】名词解释

文章目录一、新型基础测绘 new fundamental surveying and mapping**二、实景三维 3D real scene**三、时空大数据平台 spatio-temporal big data platform**四、地理实体 geo-entity**五、基础地理实体 fundamental geo-entity**六、组合地理实体数据 combined geo-entity dat…

深入理解javascript原型和闭包

原文链接http://www.cnblogs.com/wangfupeng1988/p/3977924.html 对象是属性的集合。 function show(x) {console.log(typeof(x)); // undefinedconsole.log(typeof(10)); // numberconsole.log(typeof(abc)); // stringconsole.log(typeof(true)); // booleanconsole.lo…

薪资高压线

阅读本文大概需要5分钟。最近一名读者咨询一个问题&#xff1a;洋哥&#xff0c;最近公司有一名同事因为打探其他人薪资被开除了&#xff0c;为啥我们公司要把薪资设置为高压线。这是个好问题&#xff0c;解答完他的疑惑后想起了一年多前写过一篇&#xff0c;彼时读者还比较少&…

达摩院年终预测出炉:2022 十大科技趋势,AI for Science 高居榜首

作为“一所探索科技未知的研究院”&#xff0c;阿里巴巴达摩院成立至今已经四年了。 这四年来&#xff0c;达摩院秉持着“探索科技位置&#xff0c;以人类愿景为驱动力&#xff0c;开展基础科学和颠覆式技术创新研究”的原则与使命&#xff0c;在基础科研和硬科技发展上“遍地生…

chrome调试工具高级不完整使用指南(基础篇)

一、前言 本文记录的是作者在工作上面对chrome的一些使用和情况的分析分享&#xff0c;内容仅代表个人的观点。转发请注明出处(http://www.cnblogs.com/st-leslie/),谢谢合作 二、浏览器模块介绍 由于chrome浏览器一直在不断的进行更新迭代&#xff0c;会不断的新增功能&#x…

新型基础测绘与实景三维中国建设技术文件【2】基础地理实体分类、粒度及精度基本要求

《新型基础测绘体系建设试点技术大纲》指出&#xff0c;新型基础测绘将以“基础地理实体”为核心的成果模式创新为切入点&#xff0c;带动技术体系、生产组织体系和政策标准体系的全面创新&#xff0c;从而实现基础测绘高质量发展。 基础地理实体作为新型基础测绘产品体系的核心…

构建和实现单点登录解决方案(转载于IBMdeveloperWorks)

将一个开放源码的基于 Java 的身份验证组件集成进 Web 门户中 在现有的应用程序中实现单点登录解决方案&#xff08;single sign-on&#xff0c;SSO&#xff0c;即登录一次&#xff0c;就可以向所有网络资源验证用户的身份&#xff09;是非常困难的&#xff0c;但是在构建复杂的…

分享一个基于Abp 和Yarp 开发的API网关项目

这个项目起源于去年公司相要尝试用微服务构建项目,在网关的技术选型中,我们原本确认了ApiSix 网关,如果需要写网关插件需要基于Lua脚本去写,我和另外一个同事当时基于这个写了一个简单的插件,但是开发测试以及发布都很麻烦,而且使用Lua脚本作为插件的开发语言本身也不是我们强项…

罗振宇2022“时间的朋友”跨年演讲全文稿(pdf)

2021年12月31日20:30&#xff0c;五粮液成都金融城演艺中心&#xff0c;罗振宇“时间的朋友”跨年演讲如约而至。 罗胖曾发下大愿望&#xff1a;跨年演讲要连办二十年。今年是第七场&#xff0c;也是最特殊的一场&#xff0c;罗胖面对12000个空座位&#xff0c;用53个好故事&am…

08.LoT.UI 前后台通用框架分解系列之——多样的Tag选择器

LOT.UI分解系列汇总&#xff1a;http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下&#xff1a;https://github.com/dunitian/LoTCodeBase/tree/master/LoTUI 这个必须说下&#xff0c;本来是用Bootstrap-Select做的&#xff0c;很漂亮&#xff0c;正好…

jquery文档加载完毕后执行的几种写法

2019独角兽企业重金招聘Python工程师标准>>> 1.js文档加载完毕 标签内 οnlοad"test()"window.οnlοadfunction(){}2.jquery文档加载完毕 //方式1 $(document).ready(function(){//TODO }); //方式2 $(function(){//TODO }) //方式3 $(function($){//TO…

新型基础测绘与实景三维中国建设技术文件【3】基础地理实体空间身份编码规则

基础地理实体是新型基础测绘产品体系中的核心成果&#xff0c;是推动基础测绘工作转型升级的关键。与现有的测绘地理信息数据不同&#xff0c;基础地理实体具有多粒度、多模态、多层次&#xff0c;以及搭载结构化、半结构化和非结构化多样化信息的鲜明特点。 基础地理实体空间…

oracle 表 视图 存储过程 序列 job

table 表--delete tabledrop table Test1;-- Create tablecreate table TEST1(ID NUMBER,T_NAME VARCHAR2(100),DT DATE);-- 添加注释comment on column TEST1.T_NAME is 名称;--添加age字段alter table Test1 add (age NUMBER(8));--删除字段alter table TABLE_NAME …

[转]Docker 大势已去,Podman 即将崛起

Podman Podman 什么是Podman&#xff1f;Podman和Docker的主要区别是什么&#xff1f;Podman的使用与docker有什么区别&#xff1f;Podman 常用命令 容器镜像部署 PodmanPodman 加速器使用 Podman 运行一个容器列出运行的容器检查正在运行的容器查看一个运行中容器的日志查看一…

基于Kubernetes v1.24.0的集群搭建(一)

一、写在前面 K8S 1.24作为一个很重要的版本更新&#xff0c;它为我们提供了很多重要功能。该版本涉及46项增强功能&#xff1a;其中14项已升级为稳定版&#xff0c;15项进入beta阶段&#xff0c;13项则刚刚进入alpha阶段。此外&#xff0c;另有2项功能被弃用、2项功能被删除。…

思科三层交换机充当路由器实现全网互通

转载于:https://blog.51cto.com/13568840/2059797

mpvue开发小程序分享朋友圈无法自定义标题解决方法

在node_modules里面找到mpvue&#xff0c;手动修改一下mpvue这个包下的index.js文件 // 用户点击右上角分享 到朋友圈 onShareTimeline: rootVueVM.$options.onShareTimeline? function (options) { return callHook$1(rootVueVM, onShareTimeline, options); } : null,找到 L…