冒泡排序

通过相邻元素的比较和交换,使得每一趟循环都能找到未有序数组的最大值或最小值。

最好:O(n),只需要冒泡一次数组就有序了。

最坏: O(n²)

平均: O(n²)

*单项冒泡

  function bubbleSort(nums) {
for (let i=0 , len=nums.length; i<len-1; i++) {
//如果一轮比较中没有需要交换的数据,则说明数组已经有序,主要是为了对[5,1,2,3,4]之类的数组进行优化。
let mark = true;
for (let j = 0; j < len-i-1; i++) {
if (nums[j] > nums[j+1]) {
[nums[j],nums[j+1]] = [nums[j+1],nums[j]]
mark = false
}
}
if (mark) return nums
}
}

双向冒泡

普通的冒泡排序在一趟循环中只能找出一个最大值或最小值,双向冒泡则是多一轮循环既找出最大值也找出最小值

     function bubbleSort_twoWays(nums) {
let low = 0
let high = nums.length - 1
while(low < high) {
let mark = true
// 找到最大值放到到右边
for (let i=low; i<high; i++) {
if(nums[i] > nums[i+1]) {
[nums[i],nums[i+1]] = [nums[i+1],nums[i]]
mark = false
}
}
high--
// 找到最小值放到左边
for(let j=high;j>low;j--) {
if(nums[j] < nums[j-1]) {
[nums[j],nums[j-1]] = [nums[j-1],nums[j]]
mark = false
}
}
low++
if(mark) return nums
}
}

选择排序

和冒泡排序相似,区别在于选择排序是将每一个元素和它后面的元素进行比较和交换。

最好: O(n²)

最坏: O(n²)

平均: O(n²)

 function selectSort(nums) {
for (let i = 0, len = nums.length; i < len; i++) {
for (let j = i + 1; j < len; j++) {
if (nums[i] > nums[j]) {
[nums[i], nums[j]] = [nums[j], nums[i]]
}
}
}
return nums
}

插入排序

以第一个元素作为有序数组,其后的元素通过在这个已有序的数组中找到合适的位置并插入。

最好: O(n),原数组已经是升序的。

最坏: O(n²)

平均: O(n²)

function insertSort(nums) {
for (let i = 1,len = nums.length;i < len; i++) {
let temp = nums[i]
let j = i
while (j >= 0 && temp < nums[j-1]) {
nums[j] = nums[j-1]
j--
}
nums[j] = temp
}
return nums
}

快速排序

选择一个元素作为基数(通常是第一个元素),把比基数小的元素放到它左边,比基数大的元素放到它右边(相当于二分),再不断递归基数左右两边的序列。

最好: O(n * logn),所有数均匀分布在基数的两边,此时的递归就是不断地二分左右序列。

最坏: O(n²),所有数都分布在基数的一边,此时划分左右序列就相当于是插入排序。

平均: O(n * logn)

  • 快速排序之填坑

从右边向中间推进的时候,遇到小于基数的数就赋给左边(一开始是基数的位置),右边保留原先的值等之后被左边的值填上

计数排序

以数组元素值为键,出现次数为值存进一个临时数组,最后再遍历这个临时数组还原回原数组。因为 JavaScript 的数组下标是以字符串形式存储的,所以计数排序可以用来排列负数,但不可以排列小数。

最好: O(n + k),k是最大值和最小值的差。

最坏: O(n + k)

平均: O(n + k)

 function countingSort(nums) {
let arr = []
let max = Math.max(...nums)
let min = Math.min(...nums)
// 装桶
for (let i=0, len=nums.length; i<len; i++) {
let temp = nums[i]
arr[temp] = arr[temp] + 1 || 1
}
let index = 0
//还原数组
for (let i=min; i<=max; i++) {
while(arr[i]>0) {
nums[index++] = i
arr[i]--
}
}
return nums
}

希尔排序

通过某个增量 gap,将整个序列分给若干组,从后往前进行组内成员的比较和交换,随后逐步缩小增量至 1。希尔排序类似于插入排序,只是一开始向前移动的步数从 1 变成了 gap。

最好: O(n * logn),步长不断二分。

最坏: O(n * logn)

平均: O(n * logn)


function shellSort(nums) {
let len = nums.length
// 初始步数
let gap = parseInt(len / 2)
// 逐渐缩小步数
while (gap) {
// 从第gap个元素开始遍历
for (let i = gap; i < len; i++) {
//逐步和前面其他成员进行比较和交换
for (let j = i - gap; j >= 0; j -= gap) {
if (nums[j] > nums[j + gap]) {
[nums[j], nums[j + gap]] = [nums[j + gap], nums[j]]
} else {
break
}
}
}
gap = parseInt(gap / 2)
}
return nums
}

原文链接:https://mp.weixin.qq.com/s/Rl_fcWzcSQ7NkPnozIrt0A

《JavaScript算法》常见排序算法思路与代码实现的更多相关文章

  1. [算法] 常见排序算法总结(C语言版)

    常见排序算法总结 本文对比较常用且比较高效的排序算法进行了总结和解析,并贴出了比较精简的实现代码,包括选择排序.插入排序.归并排序.希尔排序.快速排序等.算法性能比较如下图所示: 1 冒泡排序 基本原 ...

  2. JavaScript实现常见排序算法

    列表 冒泡排序 选择排序 插入排序 快速排序 希尔排序 归并排序 冒泡排序 // 输入:[5, 6, 3, 4, 8, 0, 1, 4, 7] // 输出:[0, 1, 3, 4, 4, 5, 6, ...

  3. JavaScript版几种常见排序算法

    今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...

  4. 常见排序算法原理及JS代码实现

    目录 数组 sort() 方法 冒泡排序 选择排序 插入排序 希尔排序 归并排序 堆排序 快速排序 创建时间:2020-08-07 本文只是将作者学习的过程以及算法理解进行简单的分享,提供多一个角度的 ...

  5. 常见排序算法(附java代码)

    常见排序算法与java实现 一.选择排序(SelectSort) 基本原理:对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换:接着对不包括第一个记录以外的其他 ...

  6. 常见排序算法(JS版)

    常见排序算法(JS版)包括: 内置排序,冒泡排序,选择排序,插入排序,希尔排序,快速排序(递归 & 堆栈),归并排序,堆排序,以及分析每种排序算法的执行时间. index.html <! ...

  7. javascript数据结构与算法--高级排序算法

    javascript数据结构与算法--高级排序算法 高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法-- ...

  8. JS常见排序算法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. python常见排序算法解析

    python——常见排序算法解析   算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法 ...

  10. python——常见排序算法解析

    算法是程序员的灵魂. 下面的博文是我整理的感觉还不错的算法实现 原理的理解是最重要的,我会常回来看看,并坚持每天刷leetcode 本篇主要实现九(八)大排序算法,分别是冒泡排序,插入排序,选择排序, ...

随机推荐

  1. 黑马oracle_day02:04.oracle对象&&05.oracle编程(a)

    01.oracle体系结构 02.oracle的基本操作 03.oracle的查询 04.oracle对象&&05.oracle编程(a) 05.oracle编程(b) 04.orac ...

  2. PAT Advanced 1056 Mice and Rice (25) [queue的⽤法]

    题目 Mice and Rice is the name of a programming contest in which each programmer must write a piece of ...

  3. 虚函数重载(overwrite) 继承覆盖问题

    引言 类接口需要添加默认参数,以适应不同情况调用, 但是clang-tidy 不允许在接口上设置默认参数,ps: 可能担心继承类里接口重新设置新默认参数而导致误用的情况 #include <st ...

  4. Java架构师笔记-你必须掌握的 21 个 Java 核心技术!(干货)

    闲来无事,师长一向不(没)喜(有)欢(钱)凑热闹,倒不如趁着这时候复盘复盘.而写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,希望可以给大家一些经验,能让大家更好学习和使用Jav ...

  5. Java--平台版本、跨平台、JVM、JDK、JRE

    Java2平台版本 Java2平台包括标准版(J2SE).企业版(J2EE)和微缩版(J2ME)三个版本 J2SE 包含那些构成Java语言核心的类. J2EE 包含J2SE 中的类,并且还包含用于开 ...

  6. TFRecord 的使用

    什么是 TFRecord PS:这段内容摘自 http://wiki.jikexueyuan.com/project/tensorflow-zh/how_tos/reading_data.html 一 ...

  7. C# 基类派生类构造函数执行顺序分析

    using System; namespace ConsoleApp1 { class Program{ static void Main(string[] args){ B b = new B(); ...

  8. VMware 三种网络配置解释

    https://blog.csdn.net/noob_f/article/details/51099040 ifconfig -a 网卡名称

  9. 关于Java集合框架总结

    Java集合专门用来存放多个对象,方便程序处理数据.Java提供了多种集合类,以便满足不同的应用需求,这些集合类分为两大系列:Collection和Map List List的通用方法 boolean ...

  10. Android drawable 加载效果

    <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:ones ...