JavaScript数据结构与算法之栈与队列


Posted in Javascript onJanuary 29, 2016

学习起因

曾经有一次在逛V2EX时,碰到这么一个帖子。
数学完全还给老师了,想学回一些基础数学,大概是高中程度的,有什么书籍推荐?
发帖的楼主大学没有高数课程,出去工作时一直在从事前端的工作。感觉到数学知识的匮乏,所以想补一补数学。
看了看帖子,感觉和我很像,因为我的专业是不开高数的,我学的也是前端。也同样感觉到了数学知识匮乏所带来的困顿。同时因为自己的数学思维实在是不怎么好,所以决定努力补习数学与计算机基础知识。
当时也有人说:”前端需要什么数据结构与算法”,但是对于这个事情我有自己的看法。
我并不认为前端不需要算法之类的知识,在我看来前端具备坚实的计算机基础,对自身发展是极其有利的。我想做程序员。而不是一辈子的初级前端和码农。
也算是给自己的勉励吧。毕竟基础决定上限,再加上自己对计算机真的很感兴趣,所以学起来就算很累,但也是很幸福的。于是去网上选购了《学习JavaScript数据结构与算法》这本书,配合着去图书馆借阅的《大话数据结构》,开始了数据结构与算法的初步学习。

JavaScipt之数组操作

接下来就是数据结构的第一部分,栈。
栈是一种遵从后进先出原则(LIFO,全称为Last In First Out)的有序集合。栈顶永远是最新的元素。
举个例子就是:栈就像放在箱子里的一叠书 你要拿下面的书先要把上面的书拿开。(当然,你不能先拿下面的书。)

JavaScipt中栈的实现
首先,创建一个构造函数。

/**
 * 栈的构造函数
 */
function Stack() {

 // 用数组来模拟栈
 var item = [];
}

栈需要有如下的方法:
push(element(s)): 添加几个元素到栈顶
pop(): 移除并返回栈顶元素
peek(): 返回栈顶元素
isAmpty: 检查栈是否为空,为空则返回true
clear: 移除栈中所有元素
size: 返回栈中元素个数。
print: 以字符串显示栈中所有内容
push方法的实现
说明: 需要往栈中添加新元素,元素位置在队列的末尾。也就是说,我们可以用数组的push方法来模拟实现。

实现:

/**
 * 将元素送入栈,放置于数组的最后一位
 * @param {Any} element 接受的元素,不限制类型
 */
this.push = function(element) {
 items.push(element);
};

pop方法的实现

说明: 需要把栈顶元素弹出,同时返回被弹出的值。可以用数组的pop方法来模拟实现。
实现:

/**
 * 弹出栈顶元素
 * @return {Any} 返回被弹出的值
 */
this.pop = function() {
 return items.pop();
};

peek方法的实现
说明: 查看栈顶元素,可以用数组长度来实现。
实现:

/**
 * 查看栈顶元素
 * @return {Any} 返回栈顶元素
 */
this.peek = function() {
 return items[items.length - 1];
}

其余方法的实现
说明: 前三个是栈方法的核心,其余方法则在此一次性列出。因为下文要讲的队列,会与这部分有很大重合。
实现:

/**
 * 确定栈是否为空
 * @return {Boolean} 若栈为空则返回true,不为空则返回false
 */
this.isAmpty = function() {
 return items.length === 0
};

/**
 * 清空栈中所有内容
 */
this.clear = function() {
 items = [];
};

/**
 * 返回栈的长度
 * @return {Number} 栈的长度
 */
this.size = function() {
 return items.length;
};

/**
 * 以字符串显示栈中所有内容
 */
this.print = function() {
 console.log(items.toString());
};

实际应用

栈的实际应用比较多,书中有个十进制转二进制的函数。(不懂二进制怎么算的话可以百度)下面是函数的源代码。
原理就是输入要转换的数字,不断的除以二并取整。并且最后运用while循环,将栈中所有数字拼接成字符串输出。

/**
 * 将10进制数字转为2进制数字
 * @param {Number} decNumber 要转换的10进制数字
 * @return {Number}      转换后的2进制数字
 */
function divideBy2(decNumber) {

 var remStack = new Stack(),
  rem,
  binaryString = '';

 while (decNumber > 0) {
  rem = Math.floor(decNumber % 2);
  remStack.push(rem);
  decNumber = Math.floor(decNumber / 2);
 }

 while (!remStack.isAmpty()) {
  binaryString += remStack.pop().toString();
 }

 return binaryString;
};

到此而言,栈的学习就告一段落了。因为源代码中注释较多,所以这儿就不贴出源代码的内容了。

队列

队列与栈是很相像的数据结构,不同之处在于队列是是先进先出(FIFO:First In First Out)的。
举个例子: 火车站排队买票,先到的先买。(插队的不算),是不是很好理解了~

JavaScipt中队列的实现

队列的实现和栈很像。首先依然是构造函数:

/**
 * 队列构造函数
 */
function Queue() {
 var items = [];
}

队列需要有如下的方法:
enqueue(element(s)): 向队列尾部添加几个项
dequeue(): 移除队列的第一项(也就是排在最前面的项)
front(): 返回队列的第一个元素,也就是最新添加的那个
其余方法与队列相同

enqueue方法的实现

说明: 向队列尾部添加几个项。
实现:

/**
 * 将元素推入队列尾部
 * @param {Any} ele 要推入队列的元素
 */
this.enqueue = function(ele) {
 items.push(ele);
};

dequeue方法的实现

说明: 移除队列的第一项。
实现:

/**
 * 将队列中第一个元素弹出
 * @return {Any} 返回被弹出的元素
 */
this.dequeue = function() {
 return items.shift()
};

front方法的实现

说明: 返回队列的第一个元素,也就是最新添加的那个。
实现:

/**
 * 查看队列的第一个元素
 * @return {Any} 返回队列中第一个元素
 */
this.front = function() {
 return items[0];
};

以上的三个方法,就是队列这种数据结构的核心方法了。其实很好理解的。

实际应用
书上的是个击鼓传花的小游戏。原理就是循环到相应位置时,队列弹出那个元素。最后留下的就是赢家。
源代码如下:

/**
 * 击鼓传花的小游戏
 * @param {Array} nameList 参与人员列表
 * @param {Number} num   在循环中要被弹出的位置
 * @return {String}     返回赢家(也就是最后活下来的那个)
 */
function hotPotato(nameList, num) {
 var queue = new Queue();

 for (var i = 0; i < nameList.length; i++) {
  queue.enqueue(nameList[i]);
 }

 var eliminated = '';

 while (queue.size() > 1) {
  for (var i = 0; i < num; i++) {
   queue.enqueue(queue.dequeue());
  }

  eliminated = queue.dequeue();
  console.log(eliminated + " Get out!")
 }

 return queue.dequeue()
}

队列的学习到此就告一段落了。下一期将讲述另外一种数据结构: 链表。

感想

很多时候看书,直接看算法导论或者一些数据结构的书,都是很迷糊的。后来才发现,看书从自己能看懂的开始,由浅入深才是适合自己的学习方式。

Javascript 相关文章推荐
jQuery基本选择器选择元素使用介绍
Apr 18 Javascript
js动态控制table的tr、td增加及删除的具体实现
Apr 30 Javascript
Ext修改GridPanel数据和字体颜色、css属性等
Jun 13 Javascript
js实现鼠标划过给div加透明度的方法
May 25 Javascript
jQuery使用cookie与json简单实现购物车功能
Apr 15 Javascript
再次谈论Javascript中的this
Jun 23 Javascript
Javascript中获取浏览器类型和操作系统版本等客户端信息常用代码
Jun 28 Javascript
jQuery中的insertBefore(),insertAfter(),after(),before()区别介绍
Sep 01 Javascript
详解浏览器渲染页面过程
Feb 09 Javascript
webpack vue项目开发环境局域网访问方法
Mar 20 Javascript
vue如何判断dom的class
Apr 26 Javascript
layui动态渲染生成select的option值方法
Sep 23 Javascript
javascript实现表单验证
Jan 29 #Javascript
jQuery实现横向带缓冲的水平运动效果(附demo源码下载)
Jan 29 #Javascript
JavaScript判断DIV内容是否为空的方法
Jan 29 #Javascript
基于javascript实现listbox左右移动
Jan 29 #Javascript
关于获取DIV内部内容报错的原因分析及解决办法
Jan 29 #Javascript
jQuery模拟360浏览器切屏效果幻灯片(附demo源码下载)
Jan 29 #Javascript
js实现滚动条滚动到某个位置便自动定位某个tr
Jan 20 #Javascript
You might like
PHP删除HTMl标签的三种解决方法
2013/06/30 PHP
php实现把url转换迅雷thunder资源下载地址的方法
2014/11/07 PHP
php使用wordwrap格式化文本段落的方法
2015/03/17 PHP
php语言的7种基本的排序方法
2020/12/28 PHP
用 Javascript 验证表单(form)中的单选(radio)值
2009/09/08 Javascript
jQuery1.6 使用方法一
2011/11/23 Javascript
详解使用grunt完成requirejs的合并压缩和js文件的版本控制
2017/03/02 Javascript
JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
2017/06/19 Javascript
javascript定时器取消定时器及优化方法
2017/07/08 Javascript
从setTimeout看js函数执行过程
2017/12/19 Javascript
如何快速解决JS或Jquery ajax异步跨域的问题
2018/01/08 jQuery
vue使用自定义icon图标的方法
2018/05/14 Javascript
浅谈JavaScript_DOM学习篇_图片切换小案例
2019/03/19 Javascript
在vue中实现给每个页面顶部设置title
2020/07/29 Javascript
[04:26]DOTA2上海特锦赛小组赛第二日 TOP10精彩集锦
2016/02/27 DOTA
Python中的深拷贝和浅拷贝详解
2015/06/03 Python
在主机商的共享服务器上部署Django站点的方法
2015/07/22 Python
Python编程对列表中字典元素进行排序的方法详解
2017/05/26 Python
Django项目开发中cookies和session的常用操作分析
2018/07/03 Python
Python后台开发Django的教程详解(启动)
2019/04/08 Python
详解Python可视化神器Yellowbrick使用
2019/11/11 Python
Python中logging日志库实例详解
2020/02/19 Python
如何从csv文件构建Tensorflow的数据集
2020/09/21 Python
html5-Canvas可以在web中绘制各种图形
2012/12/26 HTML / CSS
加拿大时尚床上用品零售商:QE Home | Quilts Etc
2018/01/22 全球购物
经济实惠的名牌太阳镜和眼镜:Privé Revaux
2021/02/07 全球购物
别名指示符是什么
2012/10/08 面试题
中科软笔试题和面试题
2014/10/07 面试题
单位创先争优活动方案
2014/01/26 职场文书
消防安全承诺书
2014/05/22 职场文书
党的群众路线个人对照检查材料
2014/09/23 职场文书
个人查摆问题及整改措施
2014/10/16 职场文书
经典格言警句:没有热忱,世间便无进步
2019/11/13 职场文书
Pyqt5将多个类组合在一个界面显示的完整示例
2021/09/04 Python
Mysql中有关Datetime和Timestamp的使用总结
2021/12/06 MySQL
使用kubeadm命令行工具创建kubernetes集群
2022/03/31 Servers