常用的数据结构:队列、栈、链表、树等…
- 队列
- 栈
- 后进先出,push pop
- 举例: 方法调用栈、路由切换、浏览器对而历史记录(两个栈)、判断标签是否闭合
1. 栈型结构举例
1.1 方法调用栈
function a(){
function b(){
function c(){
}
c();
}
b();
}
a();
- 错误的说法:每次执行都会创建一个作用域。
- 错误的原因:声明时就定义了作用域,而不是执行时创建的。
- 运行时产生的是执行上下文。这里所谓的栈,就是执行上下文栈。
- 上面这段代码,执行上下文栈是:[a, b, c],因为先执行的是a,a执行了再执行b,最后是c,所以是a, b, c。但是执行完后,销毁的顺序先是c,等c销毁完了是b,最后是a
- 上面所说的执行上下问栈,是一层层的关系,并不是包含关系,并不是说c的执行上下文在b的里面,而是说整个执行栈中,c的执行上下文在b的上面
1.2 浏览器的历史记录
- 有两个栈,假设栈A和栈B
- 当我进入www.baidu.com时,那么就会在栈A中push,栈A就成了[www.baidu.com]
- 这时我再进去www.taobao.com时,那么就会在栈A中再push,栈A就成了[www.baidu.com, www.taobao.com]
- 然后这时候我按浏览器后退键,那么栈A就会pop,栈A就成了[www.baidu.com],这时候栈B就会push进栈A出来的网站,也就是栈B变成了[www.taobao.com]
- 如果这时候按前进,B就会pop,将pop出的给栈A,也就是A会push进去。再按后退,A就会pop出去,B会push进A出来的网站。
- 经过上面一系列操作后,这时候栈A是[www.baidu.com],栈B是[www.taobao.com]。如果这时候在浏览器输入www.jd.com,那么栈B就会被清空,栈A就会push进www.jd.com,也就是A变成了[www.baidu.com, www.jd.com],栈B就成了[]
- 这时候你前进后退就跟之前一样了
1.3 判断标签是否闭合
- 比如有
- 当我遇到开始标签的时候,就往栈中push,如上面就是[div, span]
- 当我遇到结束标签的时候,就从栈中pop,比如上面先遇到,那么栈就成了[div],又遇到,就栈就成了[]
- 最后如果栈是空的,那么说明这段html中所有标签都是闭合的,否则就是有问题的,当然单标签除外。
2. 手写一个链表结构
class Node{
constructor(element, next){
this.element = element;
this.next = next;
}
}
class LinkedList{
constructor(){
this.head = null;
this.size = 0;
}
add(index, element){
if (arguments.length === 1) {
element = index;
index= this.size;
}
if (index < 0 || index > this.size) throw new Error('链表索引异常');
if (index === 0) {
let oldHead = this.head;
this.head = new Node(element, oldHead)
} else {
let preNode = this.getNode(index - 1);
preNode.next = new Node(element, preNode.next);
}
this.size++;
}
remove(index){
if (index < 0 || index >= this.size) throw new Error('链表索引异常');
let oldNode = null;
if (index === 0) {
oldNode = this.head;
this.head = oldNode && oldNode.next;
} else {
let prevNode = this.getNode(index - 1);
oldNode = prevNode.next;
prevNode.next = prevNode.next.next;
}
this.size--;
return oldNode && oldNode.element;
}
getNode(index){
let current = this.head;
for(let i = 0; i < index; i++) {
current = current.next;
}
return current;
}
length(){
return this.size;
}
}
module.exports = LinkedList;
3.将列表封装成队列
const LinkedList = require('./6.链表结构');
class Queue{
constructor(){
this.ll = new LinkedList();
}
offer(element){
this.ll.add(element);
return this;
}
poll(){
this.ll.remove(0);
return this;
}
getQueue(){
let queue = [];
for(let i = 0; i < this.ll.length(); i++) {
let current = this.ll.getNode(i).element;
queue.push(current)
}
return queue;
}
}
module.exports = Queue;
|