队列
一.定义
队列(queue)是一种先进先出的线性表,简称FIFO。
在表一端(表尾)插入 push,在另一端(表头)删除 shift。
和栈相反 先进先出的一个数据结构
按照常识理解就是银行排号办理业务, 先去领号排队的人, 先办理业务
二.特点
1)在表一端(表尾)插入,在另一端(表头)删除的线性表。
2)表的插入操作称为入队,表的取出操作称为出队。
3)队列的存储结构分为顺序存储或链式存储,顺序存储称为顺序队,链式存储称为链队。以循环顺序队列更常见。
4)队列分为两种:双向队列和单向队列 。
单向队列(队列):只能在一端删除数据,另一端插入数据。
双向队列(双端队列):两端都可以进行插入数据和删除数据操作。
js中没有队列的数据类型,但我们可以通过 Array来模拟一个
const queue = [];
// 入队
queue.push(1);
queue.push(2);
// 出队
const first = queue.shift();
const end = queue.shift();
最近的请求次数
var RecentCounter = function () {
// 初始化队列
this.q = [];
};
// 输入 inputs = [[],[1],[100],[3001],[3002]] 请求间隔为 3000ms
// 输出 outputs = [null,1,2,3,3]
// 时间复杂度 O(n) n为剔出老请求的长度
// 空间复杂度 O(n) n为最近请求的次数
RecentCounter.prototype.ping = function (t) {
// 如果传入的时间小于等于最近请求的时间,则直接返回0
if (!t) return null
// 将传入的时间放入队列
this.q.push(t);
// 如果队头小于 t - 3000 则剔除队头
while (this.q[0] < t - 3000) {
this.q.shift();
}
// 返回最近请求的次数
return this.q.length;
};
html 节点 实现 队列 广度优先
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="parent">
<div class="child-1">
<div class="child-1-1">
<div class="child-1-1-1">
a
</div>
</div>
<div class="child-1-2">
<div class="child-1-2-1">
b
</div>
</div>
<div class="child-1-3">
c
</div>
</div>
<div class="child-2">
<div class="child-2-1">
d
</div>
<div class="child-2-2">
e
</div>
</div>
<div class="child-3">
<div class="child-3-1">
f
</div>
</div>
</div>
</body>
<script>
const el = document.querySelector('.parent')
// 广度优先
let widthTraversal2 = (node) => {
let nodes = []
let stack = []
if (node) {
stack.push(node)
while (stack.length) {
let item = stack.shift()
let children = item.children
nodes.push(item)
// 队列,先进先出
// nodes = [] stack = [parent]
// nodes = [parent] stack = [child1,child2,child3]
// nodes = [parent, child1] stack = [child2,child3,child1-1,child1-2]
// nodes = [parent,child1,child2]
for (let i = 0; i < children.length; i++) {
stack.push(children[i])
}
}
}
return nodes
}
console.log(widthTraversal2(el));
</script>
</html>
栈
栈的定义
一个后进先出的数据结构
按照常识理解就是有序的挤公交,最后上车的人会在门口,然后门口的人会最先下车
栈(stack)是限定仅在表尾进行插入或者删除的线性表。对于栈来说,表尾端称为栈顶(top),表头端称为栈低(bottom)。不含元素的空表称为空栈。因为栈限定在表尾进行插入或者删除,所以栈又被称为后进先出的线性表(简称LIFO:Last in, First out.结构)。
栈的插入操作:叫做进栈,也叫作压栈,入栈。 push
栈的删除操作:叫做出栈,也叫弹栈。 pop
js中没有栈的数据类型,但我们可以通过Array来模拟一个
const stack = [];
stack.push(1); // 入栈
stack.push(2); // 入栈
const item1 = stack.pop(2); //出栈的元素
十进制转二进制
// 时间复杂度 O(n) n为二进制的长度
// 空间复杂度 O(n) n为二进制的长度
const dec2bin = (dec) => {
// 创建一个字符串
let res = "";
// 创建一个栈
let stack = []
// 遍历数字 如果大于0 就可以继续转换2进制
while (dec > 0) {
// 将数字的余数入栈
stack.push(dec % 2);
// 除以2
dec = dec >> 1;
}
// 取出栈中的数字
while (stack.length) {
res += stack.pop();
}
// 返回这个字符串
return res;
};
判断字符串的有效括号
// 时间复杂度O(n) n为s的length
// 空间复杂度O(n)
const isValid = (s) => {
// 如果长度不等于2的倍数肯定不是一个有效的括号
if (s.length % 2 === 1) return false;
// 创建一个栈
let stack = [];
// 遍历字符串
for (let i = 0; i < s.length; i++) {
const c = s[i];
// 如果是左括号就入栈
if (c === '(' || c === "{" || c === "[") {
stack.push(c);
} else {
// 如果不是左括号 且栈为空 肯定不是一个有效的括号 返回false
if (!stack.length) return false
// 拿到最后一个左括号
const top = stack[stack.length - 1];
// 如果是右括号和左括号能匹配就出栈
if ((top === "(" && c === ")") || (top === "{" && c === "}") || (top === "[" && c === "]")) {
stack.pop();
} else {
// 否则就不是一个有效的括号
return false
}
}
}
return stack.length === 0;
};
html 节点 实现栈 深度优先
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="parent">
<div class="child-1">
<div class="child-1-1">
<div class="child-1-1-1">
a
</div>
</div>
<div class="child-1-2">
<div class="child-1-2-1">
b
</div>
</div>
<div class="child-1-3">
c
</div>
</div>
<div class="child-2">
<div class="child-2-1">
d
</div>
<div class="child-2-2">
e
</div>
</div>
<div class="child-3">
<div class="child-3-1">
f
</div>
</div>
</div>
</body>
<script>
const el = document.querySelector('.parent')
// 深度优先
let deepTraversal1 = (node) => {
let nodes = []
// 栈
let stack = []
if (node) {
// 栈中 push 一个跟节点
stack.push(node)
// 如果栈有值
while (stack.length) {
// 拿到栈的最后一个值
let item = stack.pop()
// 最后一个值的子节点
let children = item.children
// push 到 nodes
nodes.push(item)
// 先进后出
// 倒叙遍历 注意:::: 因为是要深度优先 就先把有所当前的倒叙进入
// 第一个 parent
// 第二个 child-1
// nodes = [parent] chilren = [child3,child2,child1]
// nodes = [parent,child1] chilren = [child3,child2]
// nodes = [parent,child1] chilren = [child3,child2,child1-1,child1-1-1,...]
for (let i = children.length - 1; i >= 0; i--) {
// 把每一项添加到数据里面 最后 然后在通过 pop 拿到
stack.push(children[i])
}
}
}
return nodes
}
console.log(deepTraversal1(el));
</script>
</html>