JavaScript中的排序算法

  • 一、评判算法的标准
  • 二、算法的分类
  • 三、经典排序算法的性能指标
  • 1.冒泡排序
  • 2.选择排序
  • 3.插入排序
  • 4.Shell希尔排序(分组插入排序)
  • 5.快速排序
  • 6.归并排序
  • 7.堆排序
  • 8.排序两个有序数组

本文参考博客一
本文参考博客二
@各个算法原理
@各个算法原理详细文字描述

一、评判算法的标准

评判算法的性能高低主要从算法的执行时间和所需要占用的存储空间两个方面衡量。
时间复杂度:
时间复杂度的计算并不是计算程序具体运行的时间,而是算法执行语句的次数。
空间复杂度:
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。

二、算法的分类

由于待排序的数量不同,在排序过程中数据占用的存储设备也会有所不同,根据在排序过程中占用的存储设备的不同,可将排序方法分为两大类,一类是内部排序,指的是待排序数据全部存放在内存中进行排序的过程;另一类是外部排序,待排序的数据量很大,以致内存不能够一次容纳全部的记录,在排序过程中需要访问外存。

排序算法分类

内部排序 插入类
直接插入排序
折半插入排序
希尔排序
交换类
冒泡排序
快速排序
选择类
简单选择排序
树形选择排序
堆排序
归并类
2-路规归并排序
分配类
基数排序
外部排序
2-路平衡归并
多路平衡归并
置换选择排序
最佳平衡树

三、经典排序算法的性能指标

Tips什么是 排序的稳定性


1.冒泡排序

算法原理:
数组中有 n 个数,比较每相邻两个数,如果前者大于后者,就把两个数交换位置;这样一来,第一轮就可以选出一个最大的数放在最后面;那么经过 n-1(数组长度 - 1) 轮,就完成了所有数的排序。

实现方案:
利用两层循环,内层循环用于把数组元素中最大的数挑选出来,外层循环用于轮询除最大数外剩下元素的需要进行冒泡的次数。

算法评价:
平均复杂度:o(n^2)
空间复杂度:o(1)
稳定性:稳定

代码详情:

 var arrData = [13,8,12,10,54,9,65,27,49,76,33];function BubbleSort (arr) {for(let j=0;j<arr.length -1;j++){//finish作为标志位,判断是否已经排序结束var finish = true;for(let i=0;i<arr.length - 1 -j;i++){if(arr[i] > arr[i+1]){/*var data = arr[i];arr[i] = arr[i+1];arr[i+1] = data;*///这三行的交换函数用ES6来写:[arr[i], arr[i+1]] = [arr[i+1], arr[i]];finish = false;}}if(finish){break;}console.log('第次'+j+'外层循环',arr);// return arr;}}BubbleSort(arrData)

鸡尾酒排序: 双向的冒泡排序,外层循环不变,内层循环有两个;就是在每次循环把最大的数据筛选出来同时,把最小的数据也往前移。

代码详情:

var arrData = [13,8,12,10,54,9,65,27,49,76,33];function coaktailBubbleSort(arr) {const length = arr.length;let low = 0;let high = length - 1;while(low < high) {let finish = false;  //规定标志位for (let j = low; j < high; j++) {if(arr[j] > arr[j+1]) {[arr[j], arr[j+1]] = [arr[j+1], arr[j]];finish = true;}}if(!finish) {break;//如果一次交换也没有发生,那直接就可以跳出,结束排序}high--;finish = false;  //再次重置标志位for (let j = high; j > low; j--) {if (arr[j] < arr[j-1]) {[arr[j-1], arr[j]] = [arr[j], arr[j-1]];finish = true;}}if(!finish) {break;}low++;}console.log('排序完毕',arr);return arr;}coaktailBubbleSort(arrData);

2.选择排序

算法原理:
从数组第一个元素开始,与其他所有元素比较,将最小的元素放在第一位;然后从第二个元素开始,与剩余其他所有元素比较,将最小的元素放在第二位;以此类推进行n-1次运算。

实现方案:
两个嵌套的循环,内层循环用于筛选出最小的数据,外层循环用于控制筛选次数。

算法评价:
平均复杂度:o(n^2)
空间复杂度:o(1)
稳定性:不稳定

代码实现:

     var arrData = [13,8,12,10,54,9,65,27,49,76,33];function selectSort(arr) {for (var i = 0; i < arr.length; i++) {for (var j = i + 1; j < arr.length; j++) {if (arr[i] > arr[j]) {/**let temp = arr[j];arr[j] = arr[i];arr[i] = temp;*//*上面三句可以替换为es6写法*/[arr[i],arr[j]] = [arr[j],arr[i]]}}}console.log('排序完毕',arr);return arr;}selectSort(arrData);

3.插入排序

算法原理:
(1)直接插入排序:将数组中的第一个元素作为有序序列,将第二个元素与它比较后插入,再把这两个当作有序序列,将第三个元素与前面的比较后插入以此类推到最后一个元素与所有元素比较。
(2)二分插入排序:将寻找每个数插入位置的方法改为折半比较即可
实现方案:
利用两层循环,外循环用于元素的后移,内循环用于元素的插入。
算法评价:
平均复杂度:o(n^2) 空间复杂度:o(1) 稳定性:稳定
直接插入排序:
最佳情况:输入数组按升序排列。T(n) = O(n)
最坏情况:输入数组按降序排列。T(n) = O(n2)
平均情况:T(n) = O(n2)
二分法插入排序:
最佳情况:T(n) = O(nlogn)
最差情况:T(n) = O(n2)
平均情况:T(n) = O(n2)
直接插入排序:

 var arrData = [13,8,12,10,54,9,65,27,49,76,33];function insertionSort(arr) {for (let outer = 1; outer < arr.length; outer++) {let temp = arr[outer];let inner = outer;while (inner > 0 && arr[inner - 1] > temp) {arr[inner] = arr[inner - 1];inner--}arr[inner] = temp}console.log('排序完毕',arr)}insertionSort(arrData);

二分法插入排序:

     var arrData = [13,8,12,10,54,9,65,27,49,76,33];function binaryInsertSort(arr){for (var i = 1; i < arr.length; i++) {var key = arr[i], left = 0, right = i - 1;while (left <= right) {var middle = parseInt((left + right) / 2);if (key < arr[middle]) {right = middle - 1;} else {left = middle + 1;}}for (var j = i - 1; j >= left; j--) {arr[j + 1] = arr[j];}arr[left] = key;}console.log('排序完成',arr)return arr;}binaryInsertSort(arrData);

4.Shell希尔排序(分组插入排序)

算法原理:
希尔排序的实质是分组插入排序,该方法又称缩小增量排序。该方法的基本思想是:先将整个待排元素序列分割为若干个子序列(由相隔某个‘增量’的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待这个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况)效率是很高的,因此希尔排序在时间效率上有较大的提高。
实现方案:
把数组按下标的一定增量分组,然后对每组使用直接插入排序
算法评价:
平均复杂度:o(nlogn) 空间复杂度:o(1) 稳定性:不稳定
代码详情:

var arrData = [13,8,12,10,54,9,65,27,49,76,33];function shallSort(array) {var increment = array.length;var i;var temp; //暂存var count = 0;do {//设置增量increment = Math.floor(increment / 3) + 1;for (i = increment ; i < array.length; i++) {console.log(increment);if (array[i] < array[i - increment]) {temp = array[i];for (var j = i - increment; j >= 0 && temp < array[j]; j -= increment) {array[j + increment] = array[j];}array[j + increment] = temp;}}}while (increment > 1);console.log('排序完成',array);return array;}shallSort(arrData);

5.快速排序

该算法更多详细介绍:
@快速排序一
@快速排序二
算法原理:
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
案例一:

var arrData = [13,8,12,10,54,9,65,27,49,76,33];
function quickSort(arr){if (arr.length <= 1){return arr};var pivotIndex = Math.floor(arr.length / 2);var pivot = arr.splice(pivotIndex,1)[0];var left = [];var right = [];for (var i = 0; i < arr.length; i++){if(arr[i] < pivot) {left.push(arr[i]);}else{right.push(arr[i]);}}var res =  quickSort(left).concat([pivot],quickSort(right));console.log('排序完毕',res)return res;}quickSort(arrData)

案例二:有每次的结果

function quickSort(arr, i, j) {if(i < j) {let left = i;let right = j;let pivot = arr[left];while(i < j) {while(arr[j] >= pivot && i < j) {  // 从后往前找比基准小的数j--;}if(i < j) {arr[i++] = arr[j];}while(arr[i] <= pivot && i < j) {  // 从前往后找比基准大的数i++;}if(i < j) {arr[j--] = arr[i];}console.log('每次结果',arr)}arr[i] = pivot;quickSort(arr, left, i-1);quickSort(arr, i+1, right);return arr;}
}// example
let arr = [25,84,21,46,13,27,68,35,20];
console.log('排序完成===>>>>',quickSort(arr, 0 , arr.length-1));

6.归并排序

算法原理:
和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
核心思想:分治
实现方案:
主题流程:先将一个序列分成很多个不能再分割的子序列,将各个子序列分别排序后再将子序列合并。其实就是重复两个步骤:【1】分【2】合并。
实现上就可以分为两个函数,一个负责分段,一个负责合并(因为分割后的每个子序列都是有序的,合并就是两个有序数组合并的过程)
代码排序:

function merge(arr) {if(arr.length<2){return arr;}var mid = Math.floor(arr.length/2);//floor 向下取值;ceil向上取值,around 正常的四舍五入var left = arr.slice(0,mid);var right = arr.slice(mid);return sort(merge(left),merge(right));
}
function sort(left,right) {var result=[];var i=0;var j=0;while(i<left.length&&j<right.length){if(left[i]<right[j]){result.push(left[i]);i++}else{result.push(right[j]);j++}}if(i==left.length){result=result.concat(right.slice(j));}if(j==right.length){result=result.concat(left.slice(i));}console.log('排序完毕',result)return result;
}
var res = merge(arr);
console.log(res);

7.堆排序

暂无

8.排序两个有序数组

两个数组分别已经排序,将其合并成有序数组。

  1. 不太好的方案,先直接concat 在利用快排 冒泡或其他方案排序
  2. 创建结果集,分别添加两个数组元素,详情如下
/* 清空了原来的两个有序数组 */
function mergeTwoSortedArr (arr1, arr2) {var retArr = [];/* 遍历比较两个数组的首元素大小,小者 shift 出来 push 到结果数组中去 */while (arr1.length > 0 && arr2.length > 0) {if (arr1[0] < arr2[0]) {retArr.push(arr1.shift());} else if (arr1[0] > arr2[0]) {retArr.push(arr2.shift());} else {retArr.push(arr1.shift());retArr.push(arr2.shift());}}/* 将数组剩余元素移出放置到结果数组中,可能是arr1 也可能是arr2 */while (arr1.length > 0) {retArr.push(arr1.shift());}while (arr2.length > 0) {retArr.push(arr2.shift());}return retArr;
}// 示例
var arr1 = [2, 3, 5];
var arr2 = [3, 4, 7, 9];
console.log(mergeTwoSortedArr(arr1, arr2));   // [2, 3, 3, 4, 5, 7, 9]
  1. 正序或者倒序,遍历小的数组,把元素分别按照大小插入到大数组里面

JavaScript中的排序算法相关推荐

  1. JavaScript 中常见排序算法详解

    十大经典算法 一张图概括: 名词解释: n:数据规模 k:"桶"的个数 In-place:占用常数内存,不占用额外内存 Out-place:占用额外内存 稳定性:排序后2个相等键值 ...

  2. 排序算法 - 面试中的排序算法总结

    排序算法总结 查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中.因为其实现代码较短,应用较常见.所以在面试中经常会问到排序算法及其相关的问题.但万变不离其宗,只要熟悉了思想,灵活运用也不 ...

  3. android studio插入数据表中没有_学Java能拿高薪吗 Java中常见排序算法有哪些

    学Java能拿高薪吗?Java中常见排序算法有哪些?作为老牌编程语言,Java拥有广阔的市场占有率,几乎90%以上的大中型互联网应用系统在服务端开发都会首选Java.为了加入到Java这一高薪行业,很 ...

  4. algorithm中的排序算法详解

    文章目录 前言 一.algorithm是什么? 二.有哪些排序算法? sort random_shuffle merge reverse 总结 前言 雨下不停,爱意难眠,说一下algorithm中的几 ...

  5. javascript写各种排序算法

    在知乎上看到这个题目,就自己写了一下,在这里附上链接,里面有各种排序的动态图,非常形象直观,有助于新手对排序算法理解,链接:常见排序算法之JavaScript实现 首先各种排序算法都会用到的交换函数: ...

  6. JavaScript 几种排序算法实现(冒泡、选择、插入、归并、快速排序)

    1. 冒泡 // 冒泡 - 每次循环, 将两两中偏大的元素移动到右边 for (let i = 0; i < arr.length - 1; i++) {for (let j = i; j &l ...

  7. 6、java中的排序算法

    1.简介 排序是将元素按着指定关键字的大小递增或递减进行数据的排列,排序可以提高查找的效率 2.排序算法的分类 排序算法可大致分为四类七种,具体分类如下: 插入排序:直接插入排序.希尔排序 交换排序: ...

  8. std中稳定排序算法_排序算法问题:稳定排序与不稳定排序

    (给算法爱好者加星标,修炼编程内功) 作者:紫红的泪 https://www.cnblogs.com/codingmylife/archive/2012/10/21/2732980.html 前言 排 ...

  9. Java中各个排序算法比较

    之前我在javase基础中初步了解了一下冒泡排序,现在想根据创建的排序算法总结出它们在各方面的优劣性. 下图为java常见的几种排序: 之前我们在刘老师的数据结构课程上也有学过时间复杂度和空间复杂度的 ...

最新文章

  1. Go 2. 两数相加
  2. c语言三个数从小到大排序/输出_我的c语言笔记(三)
  3. 【JavaWeb】JDBC的基本操作和事务控制+登录和转账案例
  4. 正则匹配承兑的html,正则匹配闭合HTML标签(支持嵌套)
  5. 【新年假期宅家系列】动漫游戏集中营
  6. 产品小姐姐收到这个黑科技后,开心了一整天...
  7. 2018.11.05-4028-撸串(string)
  8. Java之抽象类(Abstract Class)与抽象方法(Abstract Method)
  9. React进行服务器端数据请求---fetch
  10. ESP8266(2)
  11. mysql8 启动报错:Error while setting value ‘STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DI
  12. 建立内网Windows补丁服务器
  13. 辞职信前端源码文件分享
  14. NC23053月月查华华的手机
  15. Authentication vs. Authorization 验证与授权
  16. 关于个人的文档管理 - 个人音乐管理
  17. 【驾驶技巧】 汽车驾驶经验交流——倒车技巧
  18. 网络上的推广方式都有哪些?常见的网络推广形式!
  19. 列车运行图正线数目的概念
  20. Google Earth Engine(GEE)——关于NDVI_NDWI_NDBI_EVI指数波段运算公式函数的集成和优化(2)

热门文章

  1. 苹果11手机信号不满格是什么原因「手机百科」
  2. 电脑连接无线,出现感叹号,无法上网。
  3. JAVA开发工程师知识点总结【数组集合篇】
  4. CSS画出三角形、直角三角形、梯形、直角梯形
  5. Vue中使用echarts的超详细步骤
  6. 全息投影技术,沉浸式全息投影,裸眼3D解决方案
  7. js中多个数组排列组合
  8. 安卓中getrootinactivewindow获取不到id_【牵线】女神贴(获取更多交友信息,请点击文章阅读原文查看)...
  9. 《机构投资的创新之路》读书笔记2(第4章):投资组合管理工具
  10. 【PS | 学习】明信片的制作