一、冒泡排序

算法介绍:

1.比较相邻的两个元素,如果前一个比后一个大,则交换位置。

2.第一轮把最大的元素放到了最后面。

3.由于每次排序最后一个都是最大的,所以之后按照步骤1排序最后一个元素不用比较。

function bubble_sort(arr){
var swap;
for(var i=0;i<arr.length-1;i++){
for(var j=0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
swap=arr[j];
arr[j]=arr[j+1];
arr[j+1]=swap;
}
}
}
}

冒泡算法改进:
1.设置一个标志,如果这一趟发生了交换,则为true。否则为false。如果这一趟没有发生交换,则说明排序已经完成。代码如下:

function bubble_sort_1(arr) {
var n = arr.length,
flag = true,
swap;
while(flag){
flag = false;
for(var j = 1; j<n; j++){
if(arr[j - 1]>arr[j]) {
swap = arr[j-1];
arr[j-1] = arr[j];
arr[j] = swap;
flag = true;
}0
}
n --;
}
return arr;
}

2.假如数组长度是20,如果只有前十位是无序排列的,后十位是有序且都大于前十位,所以第一趟遍历排序的时候发生交换的位置必定小于10,且该位置之后的必定有序,我们只需要排序好该位置之前的就可以,因此我们要来标记这个位置就可以了,即可以记录每次扫描中最后一次交换的位置,下次扫描的时候只要扫描到上次的最后交换位置就行了,因为后面的都是已经排好序的,无需再比较,代码如下:

function bubble_sort_2(arr) {
var n=arr.length;
var j,k;
var flag=n;
var swap;
while(flag>0) {
k=flag;
flag=0;
for(j=1;j<k;j++){
if (arr[j - 1] > arr[j])
{
swap=arr[j-1];
arr[j-1]=arr[j];
arr[j]=swap;
flag=j;
}
}
} }

3.每一次循环从两头出发算出最大和最小值,代码如下:

function bubble_sort_3(arr) {
  var low = 0;
  var high= arr.length-1; //设置变量的初始值
  var swap,j;
  while (low < high) {
    for (j= low; j< high; ++j) { //正向冒泡,找到最大者
      if (arr[j]> arr[j+1]) {
        swap = arr[j]; arr[j]=arr[j+1];arr[j+1]=swap;
      }
    }
    --high; //修改high值, 前移一位
    for (j=high; j>low; --j) { //反向冒泡,找到最小者
      if (arr[j]<arr[j-1]) {
        swap = arr[j]; arr[j]=arr[j-1];arr[j-1]=swap;
      }
    } 
    ++low; //修改low值,后移一位
  }
  return arr;
}

4.在代码3的基础上记录每次扫描最后一次交换的位置,下次扫描的时候只要扫描到上次的最后交换位置就行,同代码2,代码如下:

function bubble_sort_3(arr) {
  var low = 0;
  var high= arr.length-1; //设置变量的初始值
  var swap,j;
  while (low < high) {
    var pos1 = 0,pos2=0;
    for (let i= low; i< high; ++i) { //正向冒泡,找到最大者
      if (arr[i]> arr[i+1]) {
        swap = arr[i]; arr[i]=arr[i+1];arr[i+1]=swap;
        pos1 = i ;
      }
    }     high = pos1;// 记录上次位置     for (let j=high; j>low; --j) { //反向冒泡,找到最小者
      if (arr[j]<arr[j-1]) {
        swap = arr[j]; arr[j]=arr[j-1];arr[j-1]=swap;  
        pos2 = j;
      }
    }   
    
    low = pos2; //修改low值
  }
  return arr;
}

冒泡排序动图演示:

二、快速排序

算法介绍:

快速排序是对冒泡排序的一种改进,第一趟排序时将数据分成两部分,一部分比另一部分的所有数据都要小。然后递归调用,在两边都实行快速排序。

function quick_sort(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]);
}
} return quick_sort(left).concat([pivot],quick_sort(right));
}

快速排序动图演示:

三、选择排序

算法介绍:

选择排序就是从一个未知数据空间里,选取之最放到一个新的空间,代码如下:

function selection_sort(arr) {
  var len = arr.length;
  var minIndex, swap;
  for (var i = 0; i < len - 1; i++) {
    minIndex = i;
    for (var j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) { //寻找最小的数
        minIndex = j; //将最小数的索引保存
      }
    }
    swap = arr[i];
    arr[i] = arr[minIndex];
    arr[minIndex] = swap;
  }
  return arr;
}

选择排序动图演示:

四、插入排序

算法介绍:

1.从第一个默认被排好序的元素开始

2.取出下一个元素,在已经排序的元素序列中从后向前扫描

3.如果已排序的元素大于取出的元素,则将其分别向后移动一位

4.直到找到已排序的元素中小于或等于取出的元素,将取出的元素放到它的后一位

5.重复步骤2

代码如下:

function insertion_sort(arr) {
  for (var i = 1; i < arr.length; i++) {
    var key = arr[i];
    var j = i - 1;
    while ( arr[j] > key) {
      arr[j + 1] = arr[j];
      j--;
    }
    arr[j + 1] = key;
  }
  return arr;
}

插入排序算法改进-二分法插入排序:

function binaryInsertion_sort(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;
  }
  return arr;
}

插入排序法动图演示:

五、希尔排序

算法介绍:

希尔排序是冒泡排序的一种更高效率的实现。它与冒泡排序的不同之处在于,它会优先比较距离较远的元素。希尔排序的核心在于间隔序列的设定。

上图中先每差5为一组进行比较,之后再每差2为一组惊醒比较,最后就是两两比较。代码如下:

function shell_sort(arr) {
  var len = arr.length,
  temp,
  gap = 1;
  while(gap < len/5) { //动态定义间隔序列
    gap =gap*5+1;
  }
  for (gap; gap > 0; gap = Math.floor(gap/5)) {
    for (var i = gap; i < len; i++) {
      temp = arr[i];
      for (var j = i-gap; j >= 0 && arr[j] > temp; j-=gap) {
        arr[j+gap] = arr[j];
      }
      arr[j+gap] = temp;
    }
  }
  return arr;
}

六、归并排序

算法介绍:

作为一种典型的分而治之思想的算法应用,归并排序的实现由两种方法:

  1. 自上而下的递归(所有递归的方法都可以用迭代重写,所以就有了第2种方法)
  2. 自下而上的迭代

代码如下:

function merge_sort(arr) {  //采用自上而下的递归方法
var len = arr.length;
if(len < 2) {
return arr;
}
var middle = Math.floor(len / 2),
left = arr.slice(0, middle),
right = arr.slice(middle);
return merge(mergeSort(left), mergeSort(right));
} function merge(left, right)
{
var 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;
}

归并排序动图演示 :

七、堆排序

首先明白什么是堆,堆其实可以这么理解,类似金字塔,一层有一个元素,两层有两个元素,三层有四个元素,每层从数组中取元素,从左到右的顺序放到堆相应的位置上,也就是说每一层元素个数为2n-1 ;(n 代表行数),这就完成了建堆。

堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:

  1. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列
  2. 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列

代码如下:

var len;    //因为声明的多个函数都需要数据长度,所以把len设置成为全局变量

function buildMaxHeap(arr) {   //建立大顶堆
len = arr.length;
for (var i = Math.floor(len/2); i >= 0; i--) {
heapify(arr, i);
}
} function heapify(arr, i) { //堆调整
var left = 2 * i + 1,
right = 2 * i + 2,
largest = i; 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);
}
} function swap(arr, i, j) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
} function heapSort(arr) {
buildMaxHeap(arr); for (var i = arr.length-1; i > 0; i--) {
swap(arr, 0, i);
len--;
heapify(arr, 0);
}
return arr;
}

堆排序动图演示:

八、计数排序

算法介绍:
计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。
作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

代码如下:

function counting_sort(arr, maxValue) {
var bucket = new Array(maxValue+1),
sortedIndex = 0;
arrLen = arr.length,
bucketLen = maxValue + 1; for (var i = 0; i < arrLen; i++) {
if (!bucket[arr[i]]) {
bucket[arr[i]] = 0;
}
bucket[arr[i]]++;
} for (var j = 0; j < bucketLen; j++) {
while(bucket[j] > 0) {
arr[sortedIndex++] = j;
bucket[j]--;
}
} return arr;
}

计数排序动图演示:

九、桶排序

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。
为了使桶排序更加高效,我们需要做到这两点:

  1. 在额外空间充足的情况下,尽量增大桶的数量
  2. 使用的映射函数能够将输入的N个数据均匀的分配到K个桶中

同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。

什么时候最快(Best Cases):

当输入的数据可以均匀的分配到每一个桶中

什么时候最慢(Worst Cases):

当输入的数据被分配到了同一个桶中

代码演示:

function bucketSort(arr, bucketSize) {
if (arr.length === 0) {
return arr;
} var i;
var minValue = arr[0];
var maxValue = arr[0];
for (i = 1; i < arr.length; i++) {
if (arr[i] < minValue) {
minValue = arr[i]; //输入数据的最小值
} else if (arr[i] > maxValue) {
maxValue = arr[i]; //输入数据的最大值
}
} //桶的初始化
var DEFAULT_BUCKET_SIZE = 5; //设置桶的默认数量为5
bucketSize = bucketSize || DEFAULT_BUCKET_SIZE;
var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;
var buckets = new Array(bucketCount);
for (i = 0; i < buckets.length; i++) {
buckets[i] = [];
} //利用映射函数将数据分配到各个桶中
for (i = 0; i < arr.length; i++) {
buckets[Math.floor((arr[i] - minValue) / bucketSize)].push(arr[i]);
} arr.length = 0;
for (i = 0; i < buckets.length; i++) {
insertionSort(buckets[i]); //对每个桶进行排序,这里使用了插入排序
for (var j = 0; j < buckets[i].length; j++) {
arr.push(buckets[i][j]);
}
} return arr;
}

十、基数排序

基数排序须知:

基数排序有两种方法:

  1. MSD 从高位开始进行排序
  2. LSD 从低位开始进行排序
基数排序 vs 计数排序 vs 桶排序

这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:
基数排序:根据键值的每位数字来分配桶
计数排序:每个桶只存储单一键值
桶排序:每个桶存储一定范围的数值

代码演示:

function radix_sort(arr, maxDigit) {
  var mod = 10;
  var dev = 1;
  var counter = [];
  for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
    for(var j = 0; j < arr.length; j++) {
      var bucket = parseInt((arr[j] % mod) / dev);
      if(counter[bucket]== null) {
        counter[bucket] = [];
      }
    counter[bucket].push(arr[j]);
    }
    var pos = 0;
    for(var j = 0; j < counter.length; j++) {
      var value = null;
      if(counter[j]!=null) {
        while ((value = counter[j].shift()) != null) {
          arr[pos++] = value;
        }
      }
    }
  }
  return arr;
}

基数排序动图演示:

排序算法 JavaScript的更多相关文章

  1. 十大排序算法JavaScript实现总结

    花费了几周的时间断断续续的练习和模仿与使用JavaScript代码实现了十大排序算法. 里面有每种算法的动图和静态图片演示,看到图片可以自己先按照图片的思路实现一下. github中正文链接,点击查看 ...

  2. 十大经典排序算法(Javascript实现)

    前言 总括: 本文结合动图详细讲述了十大经典排序算法用Javascript实现的过程. 原文博客地址:十大经典排序算法 公众号:「菜鸟学前端」,回复「666」,获取一揽子前端技术书籍 人生有情泪沾衣, ...

  3. 秒杀9种排序算法(JavaScript版)

    一:你必须知道的 1> JS原型 2> 排序中的有序区和无序区 3> 二叉树的基本知识 如果你不知道上面三个东西,还是去复习一下吧,否则,看下面的东西有点吃力. 二:封装丑陋的原型方 ...

  4. 排序算法JavaScript版

    冒泡排序 function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len - 1; i++) { for (va ...

  5. JS常见排序算法

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

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

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

  7. JavaScript实现常用的排序算法

    ▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...

  8. 十大经典排序算法总结(JavaScript描述)

    前言 读者自行尝试可以想看源码戳这,博主在github建了个库,读者可以Clone下来本地尝试.此博文配合源码体验更棒哦~~~ 个人博客:Damonare的个人博客 原文地址:十大经典算法总结 这世界 ...

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

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

随机推荐

  1. C# 获取电脑硬盘剩余空间

    获取本地硬盘的所有剩余空间: 主要应用到System.IO类库的:Driveinfo.Directory,将model转换成json需要用到Newtonsoft.Json.JsonConvert.Se ...

  2. Redis简介及持久化

    Redis是一个key-value数据库,他不仅性能强劲,而且还具有复制特性以及为解决问题而生的独一无二的数据模型.可用于缓存.消息队列.发布.订阅消息.商品列表和评论列表等场景.Redis提供了5种 ...

  3. win10 MySQL8.0 zip包安装及问题解决

    1.在官网下载zip包 https://dev.mysql.com/downloads/mysql/ 2.将zip包解压到自己的工作目录中 3.配置环境变量 1)添加环境变量 MYSQL_HOME E ...

  4. python发送邮件(带附件)

    python通过stmp发送qq邮件,带附件 import smtplib from email.mime.multipart import MIMEMultipart from email.mime ...

  5. ef linq 查询某时间段内数据 踩的坑

    var now = DateTime.Now;var list =db.Jinbi_TypeLimit.Where(x => x.IsAvailable && x.JinbiTy ...

  6. 基于Ajax与用户认证系统的登录验证

    一.登录页面 from django.contrib import admin from django.urls import path from blog import views urlpatte ...

  7. Python爬虫之requests模块(2)

    一.今日内容 session处理cookie proxies参数设置请求代理ip 基于线程池的数据爬取 二.回顾 xpath的解析流程 bs4的解析流程 常用xpath表达式 常用bs4解析方法 三. ...

  8. 自适应布局下echarts引起页面跳帧

    项目上突然遇到一个问题,鼠标快速滑动有echarts画的饼图时,页面出现了跳帧.布局的高度突然发生变化然后恢复正常.高度怎么会变化呢?都是按百分比来的啊? 经过一番仔细观察,在跳帧的时候页面底部闪过了 ...

  9. List的设置值,跟变量的位置关系(变量范围的变化导致结果差别很大)

    我们想要的结果是: [RegnTypeCharge: null,null,null,null,1,null,null,null,null,null,null,null,null,null,null,] ...

  10. PLC-Heart