参考教材《数据结构考研复习指导》
栈和队列是操作受限的线性表, 比如: 不可以随便读取栈和队列中间的某个数据
栈是一个先进后出的数据结构, 只允许一端进行插入或者删除操作的线性表
进栈顺序依次为: 1, 2, 3, 4
出栈顺序依次为: 4, 3, 2, 1
例如: 往箱子里面放书(箱子和书一样大小), 要想拿出其中一本书, 是不是需要把这本书上面的所有的书都拿出来
class Stack {
constructor() {
this.items = [];
}
/**
* 往栈添加数据
*
* @param {*} element
* @memberof Stack
*/
push(element) {
this.items.push(element);
}
/**
* 弹出数据同时返回弹出的值
*
* @returns 弹出的元素值
* @memberof Stack
*/
pop() {
return this.items.pop();
}
/**
*查看栈顶元素返回栈顶元素
*
* @returns
* @memberof Stack
*/
peek() {
return this.items[this.items.length - 1];
}
/**
* 判断栈是否为空
*
* @returns 队列是否为空
* @memberof Stack
*/
isEmpty() {
return this.items.length === 0;
}
/**
* 清空栈所有内容
*
* @memberof Stack
*/
clear() {
this.items = [];
}
/**
* 返回队列的长度
*
* @returns 返回队列的长度
* @memberof Stack
*/
size() {
return this.items.length;
}
/**
* 将栈内容以字符串内容输出
*
* @memberof Stack
*/
print() {
console.log(this.items.toString());
}
}
相关题目
队列, 先进先出, 只允许在表的一端进行插入, 而在表的另一端进行删除.
例如: 排队买票, 先排队的人先买到票
class Queue {
constructor() {
this.items = [];
}
/**
* 将元素推入队列尾部
*
* @param {*} element
* @memberof Queue
*/
enqueue(element) {
this.items.push(element);
}
/**
* 将队列中第一个元素弹出
*
* @returns
* @memberof Queue
*/
dequeue() {
return this.items.shift();
}
/**
* 查看队列第一个元素
*
* @returns 返回队列第一个元素
* @memberof Queue
*/
front() {
return this.items[0];
}
/**
*判断队列是否为空
*
* @returns 返回是否为空
* @memberof Queue
*/
isEmpty() {
return this.items.length === 0;
}
/**
*打印队列元素
*
* @memberof Queue
*/
print() {
console.log(this.items.toString());
}
/**
*返回队列的长度
*
* @returns 返回队列的长度
* @memberof Queue
*/
size(){
return this.items.length;
}
}
在循环队列中, 头指针和尾指针的变化
head = (head + 1) % array.length
rear= (rear+ 1) % array.length
取模的目的: 因为是是一个循环队列, 但是实质上是一个普通数组, 要想循环, 那就需要无限取出数组下标, 下标的范围永远都是
0 ~ (array.length - 1), +1后对数组长度取模,其实就相当于求出了经过一次循环后的下标.
/**
* 循环队列
*/
class CircularQueue {
constructor(k) {
// 长度需要限制, 来达到空间的利用, k代表空间的长度
this.size = k;
this.items = [];
// 当然可以用数组索引来做, 那么就可以不需要front, read
// 指向首元素
this.front = 0;
// 指向尾元素
this.rear = 0;
}
/**
*判断循环队列是否为空
*
* @returns 判断循环队列是否为空
* @memberof CircularQueue
*/
isEmpty() {
return this.front === this.rear;
}
/**
*判断循环队列是否满
*
* @returns
* @memberof CircularQueue
*/
isFull() {
// 尾指针指向的是最后一个元素的后面一位
// 取模的目的就是可以无限取出 0 ~ this.size之间的数
return (this.rear + 1) % this.size === this.front;
}
/**
*元素入队
*
* @param {*} element
* @returns 是否入队成功
* @memberof CircularQueue
*/
enQueue(element) {
if (this.isFull()) {
return false;
}
if (this.isEmpty()) {
this.front = 0;
}
// 入队
this.items[this.rear] = element;
/**
* 尾指针加1,
* 取模的目的就是可以无限取出 0 ~ this.size - 1之间的数
*/
this.rear = (this.rear + 1) % this.size;
return true;
}
/**
*元素出队
*
* @returns 返回出队的元素
* @memberof CircularQueue
*/
deQueue() {
if (this.isEmpty()) {
return false;
}
// 删除队列头元素
this.items.splice(this.front, 1);
// 头指针加一
this.front = (this.front + 1) % this.size;
return true;
}
/**
*获取队列头元素
*
* @returns
* @memberof CircularQueue
*/
peek() {
if (this.isEmpty()) {
return false;
}
return this.items[this.front];
}
/**
*获取队列尾元素
*
* @returns
* @memberof CircularQueue
*/
tail() {
if (this.isEmpty()) {
return false;
}
return this.items[this.rear - 1];
}
/**
*打印队内元素
*
* @memberof CircularQueue
*/
print() {
console.log(this.items.toString());
}
}
let circularQueue = new CircularQueue(5);
circularQueue.enQueue(5);
circularQueue.enQueue(6);
circularQueue.enQueue(7);
circularQueue.deQueue();
circularQueue.print();
第一种
/**
* 根据优先级,进行入队操作
* 例如: 医院看病, 病情严重的优先诊断
*/
class PriorityQueue extends Queue {
/**
* ****************第一种做法****************
*
* 在插入的时候通过优先级排好位置
*
* @param {*} element 要插入的元素
* @param {*} priority 优先级
* @memberof PriorityQueue
*/
enqueue(element, priority) {
if (this.isEmpty()) {
this.items.push({
element,
priority
});
} else {
// 这里一定要加else, 如果不加的话, 第一次队列为空, 会经过if添加一次
// 然后!added 又会添加一次
let added = false;
// 越小优先级越高
for (let i = 0; i < this.items.length; i++) {
// 说明待插入的优先级高, 因此进行插入
if (priority < this.items[i].priority) {
this.items.splice(i, 0, {
element,
priority
});
added = true;
break;
}
}
//如果要添加的priority的值大于item的所有元素,直接添加在末尾即可
if (!added) {
this.items.push({
element,
priority
})
}
}
}
}
let priorityQueue = new PriorityQueue();
priorityQueue.enqueue("chenjiang", 2);
priorityQueue.enqueue("chengmengting", 1);
priorityQueue.print();
第二种
class PriorityQueue2 extends Queue {
enqueue(element, priority) {
this.items.push({
element,
priority
})
}
/**
* ****************第二种做法****************
*不管入队排序, 出队的时候看看哪个元素优先级高, 就想出来
*
* @returns
* @memberof PriorityQueue
*/
dequeue() {
let dequeueItemIndex = 0;
for (let i = 0; i < this.items.length; i++) {
if (this.items[dequeueItemIndex].priority > this.items[i].priority) {
dequeueItemIndex = i;
}
}
return this.items.splice(dequeueItemIndex, 1)[0];
}
}
let priorityQueue2 = new PriorityQueue2();
priorityQueue2.enqueue("chenjiang", 2);
priorityQueue2.enqueue("chengmengting", 1);
console.log(priorityQueue2.dequeue());
参考: https://www.cnblogs.com/xiabaoying/p/6559180.html
遇到左括号‘{’、‘[’、’(‘压入栈,栈的特点是后入先出,所以当遇到右括号‘}’、‘]’、’)'的时候,取出栈顶元素,是否满足读取的右括号,栈顶是与之相匹配的左括号。最后判断栈是否为空,为空证明该表达式没有问题,否则则说明这个表达式存在括号不匹配问题。
/**
*
*'{ [ ] }' => 输出:true
* '( [ ) ]' => 输出:false
*
* @param {*} str
*/
function check(str) {
let stack = new Stack();
let success = true;
for (v of str) {
switch (v) {
case '(':
case '[':
case '{':
stack.push(v);
break;
case ')':
case ']':
case '}':
let temp = stack.pop();
if (!((temp === '(' && v === ')') || (temp === '[' && v === ']') || (temp === '{' && v === '}'))) {
console.log("括号不匹配");
success = false;
return false;
}
break;
}
}
if (success) {
console.log("匹配成功了");
}
if (!stack.isEmpty()) {
console.info('兄弟都匹配完了, 我还留在栈里面, 没有人匹配我吗?');
}
}
check('{[]()}');