JavaScript数据结构与算法之基本排序算法定义与效率比较【冒泡、选择、插入排序】


Posted in Javascript onFebruary 21, 2019

本文实例讲述了JavaScript数据结构与算法之基本排序算法定义与效率比较。分享给大家供大家参考,具体如下:

javascript数据结构与算法--基本排序算法(冒泡、选择、排序)及效率比较

一、数组测试平台

javascript数据结构与算法--基本排序(封装基本数组的操作),封装常规数组操作的函数,比如:插入新数据,显示数组数据,还有交换数组元素等操作来调用不同的排序算法

function CArray(numElements) {
  this.dataStore = [];
  this.pos = 0;//是一个索引值,默认为0,从第一个开始
  this.numElements = numElements;//是保存所有的数组元素
  this.insert = insert;//向数组中插入一个元素的方法
  this.toString = toString;//显示数组中所有元素
  this.clear = clear;//清空数组数据
  this.setData = setData;//生成了存储在数组中的随机数字
  this.swap = swap;//交换数组中两个元素的位置
  this.bubbleSort = bubbleSort;
  /*将传入的数组,存储在datastore中*/
  for (var i = 0; i < numElements.length; ++i) {
    this.dataStore[i] = numElements[i];
  }
}
function setData() {
  for (var i = 0; i < this.numElements; ++i) {
    this.dataStore[i] = Math.floor(Math.random() *
      (this.numElements+1));
  }
}
function clear() {
  for (var i = 0; i < this.dataStore.length; ++i) {
    this.dataStore[i] = 0;
  }
}
function insert(element) {
  this.dataStore[this.pos++] = element;
}
function toString() {
  var retstr = "";
  for (var i = 0; i < this.dataStore.length; ++i) {
    retstr += this.dataStore[i] + " ";
    if (i > 0 && i % 10 == 0) {
      retstr += "\n";
    }
  }
  return retstr;
}
function swap(arr, index1, index2) {
  var temp = arr[index1];
  arr[index1] = arr[index2];
  arr[index2] = temp;
}
//测试生成一组数组数据(随机数)
var numElements = 100;
var myNums = new CArray(numElements);
myNums.setData();
console.log(myNums.toString());

17 94 81 80 25 24 73 76 24 35 81
63 81 59 4 76 30 47 73 98 18
54 36 53 47 22 60 88 41 66 24
73 94 40 45 72 74 14 61 92 48
36 12 42 11 12 82 24 84 60 1
17 98 63 36 84 13 18 50 89 26
98 1 6 54 52 69 6 52 98 14
79 28 19 69 76 99 97 100 10 7
24 54 81 73 18 21 45 73 66 30
28 56 54 21 88 31 20 86 48

二、冒泡排序算法

我们先来了解一下冒泡排序算法,它是最慢的排序算法之一,但也是一种最容易实现的排序算法。

之所以叫冒泡排序是因为使用这种排序算法排序时,数据值会像气泡一样从数组的一端漂浮到另一端。

假设正在将一组数字按照升序排列,较大的值会浮动到数组的右侧,而较小的值则会浮动到数组的左侧。

之所以会产生这种现象是因为算法会多次在数组中移动,比较相邻的数据,当左侧值大于右侧值时将它们进行互换。

JS代码如下:

function CArray(numElements) {
  this.dataStore = [];
  this.pos = 0;//是一个索引值,默认为0,从第一个开始
  this.numElements = numElements;//是保存所有的数组元素
  this.insert = insert;//向数组中插入一个元素的方法
  this.toString = toString;//显示数组中所有元素
  this.clear = clear;//清空数组数据
  this.setData = setData;//生成了存储在数组中的随机数字
  this.swap = swap;//交换数组中两个元素的位置
  this.bubbleSort = bubbleSort;//冒泡算法
  /*将传入的数组,存储在datastore中*/
  for (var i = 0; i < numElements.length; ++i) {
    this.dataStore[i] = numElements[i];
  }
}
function setData() {
  for (var i = 0; i < this.numElements; ++i) {
    this.dataStore[i] = Math.floor(Math.random() *
      (this.numElements+1));
  }
}
function clear() {
  for (var i = 0; i < this.dataStore.length; ++i) {
    this.dataStore[i] = 0;
  }
}
function insert(element) {
  this.dataStore[this.pos++] = element;
}
function toString() {
  var retstr = "";
  for (var i = 0; i < this.dataStore.length; ++i) {
    retstr += this.dataStore[i] + " ";
    if (i > 0 && i % 10 == 0) {
      retstr += "\n";
    }
  }
  return retstr;
}
function swap(arr, index1, index2) {
  var temp = arr[index1];
  arr[index1] = arr[index2];
  arr[index2] = temp;
}
function bubbleSort() {
  var numElements = this.dataStore.length;
  for (var outer = numElements; outer >= 2; --outer) {
    for (var inner = 0; inner <= outer-1; ++inner) {
      if (this.dataStore[inner] > this.dataStore[inner+1]) {
        swap(this.dataStore, inner, inner+1);
      }
    }
    console.log("outer为" + outer + ": " + this.toString());
  }
}
//测试冒泡排序算法
var numElements = [2,4,1,3];
var myNums = new CArray(numElements);
console.log("原来的数组:"+myNums.toString());
myNums.bubbleSort();
console.log("排序后的数组:"+myNums.toString());

冒泡算法代码分析如下:

原先数组为 [2,4,1,3];

1. outer为4的时候

    1. inner为0,值为2,inner+1为1,值为4,不符合,不交换。
    2. inner为1,值为4,inner+1为2,值为1,交换,数组变为[2,1,4,3]
    3. inner为2,值为4,inner+1为3,值为3,交换 数组变为[2,1,3,4]
    4. inner为3,值为4,inner+1为4,不符合 不交换。

2. outer为3的时候

    1. inner为0,值为2,inner+1为1,值为1,交换 数组变为[1,2,3,4]
    2. inner为1, 值为2,inner+1为2,值为3 不符合 不交换。
    3. inner为2, 值为3,inner+1为3,值为4,不符合 不交换。

再下面继续循环都不符合条件,所以如上就是最后一步了。这就是冒泡排序。

三、选择排序算法

选择排序从数组的开头开始,将第一个元素和其他元素进行比较。

检查完所有元素后,最小的元素会被放到数组的第一个位置,然后算法会从第二个位置继续。

这个过程一直进行,当进行到数组的倒数第二个位置时,所有的数据便完成了排序。
选择排序会用到嵌套循环。

外循环从数组的第一个元素移动到倒数第二个元素;

内循环从第二个数组元素移动到最后一个元素,查找比当前外循环所指向的元素小的元素。

每次内循环迭代后,数组中最小的值都会被赋值到合适的位置。

JS代码如下:

function CArray(numElements) {
  this.dataStore = [];
  this.pos = 0;//是一个索引值,默认为0,从第一个开始
  this.numElements = numElements;//是保存所有的数组元素
  this.insert = insert;//向数组中插入一个元素的方法
  this.toString = toString;//显示数组中所有元素
  this.clear = clear;//清空数组数据
  this.setData = setData;//生成了存储在数组中的随机数字
  this.swap = swap;//交换数组中两个元素的位置
  this.selectionSort = selectionSort;//选择排序算法
  /*将传入的数组,存储在datastore中*/
  for (var i = 0; i < numElements.length; ++i) {
    this.dataStore[i] = numElements[i];
  }
}
function setData() {
  for (var i = 0; i < this.numElements; ++i) {
    this.dataStore[i] = Math.floor(Math.random() *
      (this.numElements+1));
  }
}
function clear() {
  for (var i = 0; i < this.dataStore.length; ++i) {
    this.dataStore[i] = 0;
  }
}
function insert(element) {
  this.dataStore[this.pos++] = element;
}
function toString() {
  var retstr = "";
  for (var i = 0; i < this.dataStore.length; ++i) {
    retstr += this.dataStore[i] + " ";
    if (i > 0 && i % 10 == 0) {
      retstr += "\n";
    }
  }
  return retstr;
}
function swap(arr, index1, index2) {
  var temp = arr[index1];
  arr[index1] = arr[index2];
  arr[index2] = temp;
}
function selectionSort() {
  var min, temp;
  for (var outer = 0; outer <= this.dataStore.length-2; ++outer) {
    min = outer;
    for (var inner = outer + 1;inner <= this.dataStore.length-1; ++inner) {
      if (this.dataStore[inner] < this.dataStore[min]) {
        min = inner;
      }
    }
    swap(this.dataStore, outer, min);
    console.log("第"+outer +"次:"+myNums.toString());
  }
}
//测试排序算法
var numElements = [2,4,1,3];
var myNums = new CArray(numElements);
console.log("原来的数组:"+myNums.toString());
myNums.selectionSort();
console.log("排序后的数组:"+myNums.toString());

原来的数组:2 4 1 3
第0次:1 4 2 3
第1次:1 2 4 3
第2次:1 2 3 4
排序后的数组:1 2 3 4

四、插入排序算法

插入排序有两个循环。

外循环将数组元素挨个移动,而内循环则对外循环中选中的元素及它前面的那个元素进行比较。

如果外循环中选中的元素比内循环中选中的元素小,那么数组元素会向右移动,为外循环中的这个元素腾出位置

function CArray(numElements) {
  this.dataStore = [];
  this.pos = 0;//是一个索引值,默认为0,从第一个开始
  this.numElements = numElements;//是保存所有的数组元素
  this.insert = insert;//向数组中插入一个元素的方法
  this.toString = toString;//显示数组中所有元素
  this.clear = clear;//清空数组数据
  this.setData = setData;//生成了存储在数组中的随机数字
  this.swap = swap;//交换数组中两个元素的位置
  this.insertionSort = insertionSort;//插入排序算法
  /*将传入的数组,存储在datastore中*/
  for (var i = 0; i < numElements.length; ++i) {
    this.dataStore[i] = numElements[i];
  }
}
function setData() {
  for (var i = 0; i < this.numElements; ++i) {
    this.dataStore[i] = Math.floor(Math.random() *
      (this.numElements+1));
  }
}
function clear() {
  for (var i = 0; i < this.dataStore.length; ++i) {
    this.dataStore[i] = 0;
  }
}
function insert(element) {
  this.dataStore[this.pos++] = element;
}
function toString() {
  var retstr = "";
  for (var i = 0; i < this.dataStore.length; ++i) {
    retstr += this.dataStore[i] + " ";
    if (i > 0 && i % 10 == 0) {
      retstr += "\n";
    }
  }
  return retstr;
}
function swap(arr, index1, index2) {
  var temp = arr[index1];
  arr[index1] = arr[index2];
  arr[index2] = temp;
}
function insertionSort() {
  var temp, inner;
  //外循环将数组元素挨个移动
  for (var outer = 1; outer <= this.dataStore.length-1; ++outer) {
    temp = this.dataStore[outer];//外循环选中的元素temp
    inner = outer;
    //内循环对外循环中选中的元素temp与temp前面的元素一个个进行比较。
    //如果外循环中选中的元素temp比内循环中选中的元素小,那么数组元素会向右移动,为外循环中的这个元素腾出位置
    while (inner > 0 && (this.dataStore[inner-1] >= temp)) {
      this.dataStore[inner] = this.dataStore[inner-1];
      --inner;
    }
    this.dataStore[inner] = temp;
    console.log("第"+outer+"次:"+myNums.toString());
  }
}
//测试排序算法
var numElements = [9,1,8,6,2,3,5,4];
var myNums = new CArray(numElements);
console.log("原来的数组:"+myNums.toString());
myNums.insertionSort();
console.log("排序后的数组:"+myNums.toString());

原来的数组:9 1 8 6 2 3 5 4 //先用1和1前面的对比,9比1大,所以9向右移动一个位置,给1腾位置
      第1次:1 9 8 6 2 3 5 4 //用8与8前面的对比,9比8大,所以9向右移动一个位置,给8腾位置
      第2次:1 8 9 6 2 3 5 4 //用6与6前面的对比,8,9比6大,所以8、9向右移动一个位置,给6腾位置
      第3次:1 6 8 9 2 3 5 4
      第4次:1 2 6 8 9 3 5 4
      第5次:1 2 3 6 8 9 5 4
      第6次:1 2 3 5 6 8 9 4
      第7次:1 2 3 4 5 6 8 9
排序后的数组:1 2 3 4 5 6 8 9

五、基本排序算法的效率比较

function CArray(numElements) {
  this.dataStore = [];
  this.pos = 0;//是一个索引值,默认为0,从第一个开始
  this.numElements = numElements;//是保存所有的数组元素
  this.insert = insert;//向数组中插入一个元素的方法
  this.toString = toString;//显示数组中所有元素
  this.clear = clear;//清空数组数据
  this.setData = setData;//生成了存储在数组中的随机数字
  this.swap = swap;//交换数组中两个元素的位置
  this.bubbleSort = bubbleSort;//冒泡排序算法
  this.selectionSort = selectionSort;//选择排序算法
  this.insertionSort = insertionSort;//插入排序算法
  /*将传入的数组,存储在datastore中*/
  for (var i = 0; i < numElements.length; ++i) {
    this.dataStore[i] = numElements[i];
  }
}
function setData() {
  for (var i = 0; i < this.numElements; ++i) {
    this.dataStore[i] = Math.floor(Math.random() *
      (this.numElements+1));
  }
}
function clear() {
  for (var i = 0; i < this.dataStore.length; ++i) {
    this.dataStore[i] = 0;
  }
}
function insert(element) {
  this.dataStore[this.pos++] = element;
}
function toString() {
  var retstr = "";
  for (var i = 0; i < this.dataStore.length; ++i) {
    retstr += this.dataStore[i] + " ";
    if (i > 0 && i % 10 == 0) {
      retstr += "\n";
    }
  }
  return retstr;
}
function swap(arr, index1, index2) {
  var temp = arr[index1];
  arr[index1] = arr[index2];
  arr[index2] = temp;
}
function bubbleSort() {
  var numElements = this.dataStore.length;
  for (var outer = numElements; outer >= 2; --outer) {
    for (var inner = 0; inner <= outer-1; ++inner) {
      if (this.dataStore[inner] > this.dataStore[inner+1]) {
        swap(this.dataStore, inner, inner+1);
      }
    }
//    console.log("outer为" + outer + ": " + this.toString());
  }
}
function selectionSort() {
  var min, temp;
  for (var outer = 0; outer <= this.dataStore.length-2; ++outer) {
    min = outer;
    for (var inner = outer + 1;inner <= this.dataStore.length-1; ++inner) {
      if (this.dataStore[inner] < this.dataStore[min]) {
        min = inner;
      }
    }
    swap(this.dataStore, outer, min);
//    console.log("第"+outer +"次:"+this.toString());
  }
}
function insertionSort() {
  var temp, inner;
  //外循环将数组元素挨个移动
  for (var outer = 1; outer <= this.dataStore.length-1; ++outer) {
    temp = this.dataStore[outer];//外循环选中的元素
    inner = outer;
    //内循环则对外循环中选中的元素与它前面的那个元素进行比较。
    //如果外循环中选中的元素比内循环中选中的元素小,那么数组元素会向右移动,为外循环中的这个元素腾出位置
    while (inner > 0 && (this.dataStore[inner-1] >= temp)) {
      this.dataStore[inner] = this.dataStore[inner-1];
      --inner;
    }
    this.dataStore[inner] = temp;
//    console.log("第"+outer+"次:"+this.toString());
  }
}
/*测试冒泡、选择、插入算法的效率*/
var numElements = 10000;
var nums = new CArray(numElements);
nums.setData();
var start = new Date().getTime();
nums.bubbleSort();
var stop = new Date().getTime();
var elapsed = stop - start;
console.log("用冒泡算法,排序 " + numElements + " 个元素耗时 : " + elapsed + " milliseconds.");
start = new Date().getTime();
nums.selectionSort();
stop = new Date().getTime();
elapsed = stop - start;
console.log("用选择算法,排序 " + numElements + " 个元素耗时: " + elapsed + " milliseconds.");
start = new Date().getTime();
nums.insertionSort();
stop = new Date().getTime();
elapsed = stop - start;
console.log("用插入算法,排序 " + numElements + " 个元素耗时: " + elapsed + " milliseconds.");

运行结果:

JavaScript数据结构与算法之基本排序算法定义与效率比较【冒泡、选择、插入排序】

选择排序和插入排序要比冒泡排序快,插入排序是这三种算法中最快的。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

Javascript 相关文章推荐
JQUERY 浏览器判断实现函数
Aug 20 Javascript
js function使用心得
May 10 Javascript
异步加载script的代码
Jan 12 Javascript
append和appendTo的区别以及appendChild用法
Dec 24 Javascript
javascript定义变量时加var与不加var的区别
Dec 22 Javascript
jQuery控制网页打印指定区域的方法
Apr 07 Javascript
Javascript 高阶函数使用介绍
Jun 15 Javascript
jQuery实现的AJAX简单弹出层效果代码
Nov 26 Javascript
javascript中利用柯里化函数实现bind方法
Apr 29 Javascript
Angular5.1新功能分享
Dec 21 Javascript
jQuery实现手机号正则验证输入及自动填充空格功能
Jan 02 jQuery
React父子组件间的传值的方法
Nov 13 Javascript
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
Feb 21 #Javascript
angularjs实现table表格td单元格单击变输入框/可编辑状态示例
Feb 21 #Javascript
Vue实现table上下移动功能示例
Feb 21 #Javascript
JavaScript数组、json对象、eval()函数用法实例分析
Feb 21 #Javascript
ES6基础之解构赋值(destructuring assignment)
Feb 21 #Javascript
ES6基础之展开语法(Spread syntax)
Feb 21 #Javascript
ES6基础之默认参数值
Feb 21 #Javascript
You might like
浅析PHP中的字符串编码转换(自动识别原编码)
2013/07/02 PHP
php中\r \r\n \t的区别示例介绍
2014/02/08 PHP
Drupal读取Excel并导入数据库实例
2014/03/02 PHP
Laravel 5.4.36中session没有保存成功问题的解决
2018/02/19 PHP
PHP多进程通信-消息队列使用
2019/03/08 PHP
jQuery 技巧小结
2010/04/02 Javascript
JavaScrip单线程引擎工作原理分析
2010/09/04 Javascript
初始Nodejs
2014/11/08 NodeJs
jQuery实现类似淘宝网图片放大效果的方法
2015/07/08 Javascript
JS模仿编辑器实时改变文本框宽度和高度大小的方法
2015/08/17 Javascript
jquery自定义表单验证插件
2016/10/12 Javascript
原生JS查找元素的方法(推荐)
2016/11/22 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
2017/10/28 jQuery
vue-cli脚手架的安装教程图解
2018/09/02 Javascript
深入探讨JavaScript的最基本部分之执行上下文
2019/02/12 Javascript
浅谈Vue.js组件(二)
2019/04/09 Javascript
微信网页登录逻辑与实现方法
2019/04/29 Javascript
Vue内部渲染视图的方法
2019/09/02 Javascript
Vue搭建后台系统需要注意的问题
2019/11/08 Javascript
[48:39]Ti4主赛事胜者组第一天 EG vs NEWBEE 2
2014/07/19 DOTA
Python FTP操作类代码分享
2014/05/13 Python
Python中的对象,方法,类,实例,函数用法分析
2015/01/15 Python
fastcgi文件读取漏洞之python扫描脚本
2017/04/23 Python
Python判断两个list是否是父子集关系的实例
2018/05/04 Python
用python处理MS Word的实例讲解
2018/05/08 Python
在jupyter notebook中调用.ipynb文件方式
2020/04/14 Python
python 实现超级玛丽游戏
2020/11/25 Python
贝玲妃美国官方网站:Benefit美国
2016/08/28 全球购物
alice McCALL官网:澳大利亚时尚品牌
2020/11/16 全球购物
餐饮总经理岗位职责
2014/03/07 职场文书
新春文艺演出主持词
2014/03/27 职场文书
学生会副主席竞选稿
2015/11/19 职场文书
2016会计专业自荐信范文
2016/01/28 职场文书
php随机生成验证码,php随机生成数字,php随机生成数字加字母!
2021/04/01 PHP
Python selenium模拟网页点击爬虫交管12123违章数据
2021/05/26 Python
Python实现信息管理系统
2022/06/05 Python