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 相关文章推荐
JavaScript中this关键字使用方法详解
Mar 08 Javascript
使用delegate方法为一个tr标签加一个链接
Jun 27 Javascript
WordPress中利用AJAX异步获取评论用户头像的方法
Jan 08 Javascript
Bootstrap按钮下拉菜单组件详解
May 10 Javascript
JSON与String互转的实现方法(Javascript)
Sep 27 Javascript
JS验证图片格式和大小并预览的简单实例
Oct 11 Javascript
网页中右键功能的实现方法之contextMenu的使用
Feb 20 Javascript
AngularJS实现动态添加Option的方法
May 17 Javascript
Angular 4 指令快速入门教程
Jun 07 Javascript
vue登录注册及token验证实现代码
Dec 14 Javascript
微信小程序全局变量改变监听的实现方法
Jul 15 Javascript
javascript简单实现深浅拷贝过程详解
Oct 08 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新手入门学习方法
2011/05/08 PHP
Linux下手动编译安装PHP扩展的例子分享
2014/07/15 PHP
PHP实现十进制数字与二十六进制字母串相互转换操作示例
2018/08/10 PHP
简单的php购物车代码
2020/06/05 PHP
jquery实现微博文字输入框 输入时显示输入字数 效果实现
2013/07/12 Javascript
让alert不出现弹窗的两种方法
2014/05/18 Javascript
For循环中分号隔开的3部分的执行顺序探讨
2014/05/27 Javascript
灵活的理解JavaScript中的this指向
2016/02/25 Javascript
微信小程序 欢迎界面开发的实例详解
2016/11/30 Javascript
手机软键盘弹出时影响布局的解决方法
2016/12/15 Javascript
NodeJS创建最简单的HTTP服务器
2017/05/15 NodeJs
微信小程序 sha1 实现密码加密实例详解
2017/07/06 Javascript
vue-cli启动本地服务局域网不能访问的原因分析
2018/01/22 Javascript
Vue中的v-for循环key属性注意事项小结
2018/08/12 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
Node.js使用MongoDB的ObjectId作为查询条件的方法
2019/09/10 Javascript
[01:02:48]2018DOTA2亚洲邀请赛 4.1 小组赛 A组 LGD vs OG
2018/04/02 DOTA
python3 模拟登录v2ex实例讲解
2017/07/13 Python
解决pycharm无法调用pip安装的包问题
2018/05/18 Python
numpy数组广播的机制
2019/07/12 Python
python 实现多维数组转向量
2019/11/30 Python
python实现异常信息堆栈输出到日志文件
2019/12/26 Python
python GUI库图形界面开发之PyQt5单选按钮控件QRadioButton详细使用方法与实例
2020/02/28 Python
Python局部变量与全局变量区别原理解析
2020/07/14 Python
python 实现全球IP归属地查询工具
2020/12/18 Python
突袭HTML5之Javascript API扩展2—地理信息服务及地理位置API学习
2013/01/31 HTML / CSS
HTML5注册页面示例代码
2014/03/27 HTML / CSS
HTML5进度条特效
2014/12/18 HTML / CSS
护士毕业生自荐信
2014/02/07 职场文书
亮剑精神演讲稿
2014/05/23 职场文书
献爱心大型公益活动策划方案
2014/09/15 职场文书
演讲开场白台词大全
2015/05/29 职场文书
教师见习总结范文
2015/06/23 职场文书
Python基础之条件语句详解
2021/06/16 Python
Go语言读取txt文档的操作方法
2022/01/22 Golang
JS实现刷新网页后之前浏览位置保持不变示例详解
2022/08/14 Javascript