一、 栈
1. 栈的定义
栈,是限定仅在表尾进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶,另一端称为栈底,有着后进先出(last in first out,简写LIFO)的特性。

日常生活中的例子,比如弹夹:最后压入的子弹最先射出

2. 栈的实现
从数据存储的角度来看,实现栈结构有2种常见方式:
- 基于数组实现
- 基于链表实现
本文实现栈结构基于数组
2.1 封装栈类
// 封装栈类
function Stack() {
// 栈的属性
this.items = [];
};
2.3 栈的常见操作与JavaScript实现:
- push(element):添加一个新元素到栈顶
- pop():移除栈顶的元素,同时返回被移除元素
- peek():返回栈顶的元素,但并不对栈顶的元素做出任何的修改
- isEmpty():检查栈内是否有元素,如果有返回true,没有返回false
- clear():清除栈里的元素
- size():返回栈的元素个数
// 封装栈类
function Stack() {
// 栈的属性
this.items = [];
// 栈的方法
// 将元素压入栈
Stack.prototype.push = function (item) {
this.items.push(item);
};
// 从栈中取出元素
Stack.prototype.pop = function () {
return this.items.pop();
};
// 查看栈顶元素
Stack.prototype.peek = function () {
return this.items[this.items.length - 1];
};
// 判断栈是否为空
Stack.prototype.isEmpty = function () {
return this.items.length === 0;
};
// 获取栈中元素的个数
Stack.prototype.size = function () {
return this.items.length;
};
};
2.4 栈的使用
// 实例化一个对象
var stack = new Stack();
console.log(stack.isEmpty()); // true
stack.push(3);
stack.push(6);
stack.push(5);
stack.push(11);
console.log(stack.peek()); // 输出栈顶元素11
console.log(stack.size()); // 输出元素个数4
stack.pop(); // 删除栈顶元素11
console.log(stack.peek()); // 输出栈顶元素5
2.5 栈的应用--十进制转换二进制
十进制100转换二进制逻辑(除2取余,逆序排列),符合后进先出的栈特征
计算:100 / 2 = 50 余数:0
计算:50 / 2 = 25 余数:0
计算:25 / 2 = 12 余数:1
计算:12 / 2 = 6 余数:0
计算:6 / 2 = 3 余数:0
计算:3 / 2 = 1 余数:1
计算:1 / 2 = 0 余数:1
代码实现
// 十进制转换为二进制
function decToBin (number) {
var st = new Stack();
while (number > 0) {
st.push(number % 2);
number = Math.floor(number / 2);
}
var result = "";
while (st.size() > 0) {
result += st.pop();
}
return result;
}
2.6 栈的应用--git stash
git stash命令暂存对当前分支的所有操作,将未完成的修改保存到一个栈上,在任意时刻重新找回修改。运行该命令后,所有没有commit的代码,都会暂时从工作区移除,回到上次commit时的状态。
# 暂时保存没有提交的工作
$ git stash
Saved working directory and index state WIP on workbranch: 56cd5d4 Revert "update old files"
HEAD is now at 56cd5d4 Revert "update old files"
# 列出所有暂时保存的工作
$ git stash list
stash@{0}: WIP on workbranch: 56cd5d4 Revert "update old files"
stash@{1}: WIP on project1: 1dd87ea commit "fix typos and grammar"
# 恢复某个暂时保存的工作
$ git stash apply stash@{1}
# 恢复最近一次stash的文件
$ git stash pop
# 丢弃最近一次stash的文件
$ git stash drop
# 删除所有的stash
$ git stash clear
二、 队列
1. 队列的定义
队列和栈十分相似,他们都是线性表,元素都是有序的 。队列和栈不同的是,队列遵循先进先出(First in first out,简称FIFO)的原则。队列从尾部添加新元素,从顶部移除元素,最新添加的元素必须排列在队列的末尾。

日常生活中,最常见的队列就是排队,先进入队列的先服务,后进入的排在队尾

2. 队列的实现
从数据存储的角度来看,实现栈结构有2种常见方式:
- 基于数组实现
- 基于链表实现
本文实现队列结构基于数组(性能低于链表实现)
2.1 封装队列类
// 封装队列类
function Queue() {
// 队列的属性
this.items = [];
};
2.3 栈的常见操作与JavaScript实现:
- enqueue(element):向队列尾部添加一个(或是多个)元素
- dequeue():移除队列的第一个元素,并返回被移除的元素
- front():返回队列的第一个元素——最先被添加的也是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息,与Stack类的peek()方法类似)
- isEmpty():检查队列内是否有元素,如果有返回true,没有返回false
- size():返回队列的元素个数
// 封装队列类
function Queue() {
// 队列的属性
this.items = [];
// 队列的方法
// 将元素加入队列中
Queue.prototype.enqueue = function (item) {
this.items.push(item);
};
// 从栈中删除前端元素
Queue.prototype.dequeue = function () {
return this.items.shift();
};
// 查看前端元素
Queue.prototype.front = function () {
return this.items[0];
};
// 判断队列是否为空
Queue.prototype.isEmpty = function () {
return this.items.length === 0;
};
// 获取队列中元素的个数
Queue.prototype.size = function () {
return this.items.length;
};
};
2.4 队列的使用
// 实例化一个对象
var queue = new Queue();
console.log(queue.isEmpty()); // true
queue.enqueue(3);
queue.enqueue(6);
queue.enqueue(5);
queue.enqueue(11);
console.log(queue.front()); // 输出队列前端元素3
console.log(queue.size()); // 输出队列元素个数4
queue.dequeue(); // 删除队列元素3
console.log(queue.front()); // 输出队列前端元素6
2.5 队列的应用--斐波那契数列
要求: 使用队列计算斐波那契数列的第n项
分析: 斐波那契数列的前两项固定为1,后面的项为前两项之和,依次向后,这便是斐波那契数列。

function fibonacci(n) {
const queue = new Queue();
// 先将固定的前两项加入队列
queue.enqueue(1);
queue.enqueue(1);
let index = 0;
while(index < n - 2) {
index += 1;
// 取出队列一个元素
const delItem = queue.dequeue();
// 取出队列头部元素
const frontItem = queue.front();
// 计算下一个元素
const nextItem = delItem + frontItem;
// 将下一个元素的计算结果加入队列中
queue.enqueue(nextItem);
console.log(index, queue.front())
}
console.log(queue.size(), '队列元素个数');
// 此时队列中有两个元素,先删除再取出最后一个元素
console.log(index, queue.front());
queue.dequeue();
return queue.front();
}
console.log(fibonacci(9)); // 34