1. 栈
栈是一种后入先出(LastInFirstOut)的数据结构。可以通过数组的push和pop操作模拟实现。
其中push和pop的算法复杂度都是O(1)
2. 队列
队列是一种先入先出的数据结构(FirstInFIrstOut)的数据结构。本质上是数组的push和shift操作。
但是shift方法的算法复杂度是O(n)。
1. 队列构建
可以自己实现一个队列的数据结构
class Queue { constructor(max=100) { this.data = Array(max); this.p = 0;// 入队指针;指向下一个数据将会插入的位置 this.q = 0;// 出队指针;当前队列第一个数据所在的位置 this.max = max;// max指队列的最大容量 this.size = 0; // 初始队列为空 } // 读取对头的操作 peek() { const item = this.data[this.q]; return item; } // 入队操作 enqueue(value) { if(this.size === this.max) { // 队列溢出;可以抛出异常或者进行其他操作 throw new Error("队列overflow") } this.data[this.p++] = value; this.size++; if(this.p === this.max){ this.p = 0; } } // 出队操作-返回出队的数据 dequeue() { if(this.size === 0) { // 队列反向溢出:可以抛出异常或者进行其他操作 throw new Error("队列underflow") } const item = this.data[this.q]; this.data[this.q++] = undefined; // 将对应位置的值置为undefined this.size--; if (this.q === this.max) { this.q = 0;// 超出范围,回到起始位置 } return item; } }
示例:
/** 火车车厢通过一个环形轨道进行重排列,判断是否能得到目标的排列顺序; [1,2,3,4,5] => [1,5,2,3,4] |--4-3-2-1---|临时轨道(队列) | | [5][4][3][2][1]----|----5-------|---------[4][3][2][5][1]对应数组[1,5,2,3,4] */
按照实际情况分析,排列只能是先入先出,则数据结构应该是队列。
function resort(original, target) { // 遍历目标队列的值,如果和原始队列对应位置匹配,则从原始数据中shift()该值 // 如果不匹配则将原始数列对应的值之前的数据全局存入临时队列。 // 继续遍历,如果临时队列或者剩余原始队列的第一值和目标队列对应位置的值匹配,则shift() // 最终结果如果临时队列的值为空,则证明可以 let tempQueue = new Queue(original.size); for(let x of target.data) { if (x === tempQueue.peek()) { tempQueue.dequeue(); } else if (original.size === 0 ) { return tempQueue.size === 0 } let y = null; while(original.size > 0 && ((y=original.dequeue()) !== x)) { tempQueue.enqueue(y); } } return tempQueue.size === 0; //如果取值tempQueue.data }
测试用例:
// 测试用例 const arr1 = [1,2,3,4,5]; const arr2 = [1,3,2,4,5]; //true // const arr2 = [5,4,3,2,1]; // false // const arr2 = [1,5,2,3,4]; // true // const arr2 = [1,5,2,4,3]; // false const queue1 = new Queue(arr1.length); const queue2 = new Queue(arr2.length); for(let i=0; i<arr1.length; i++) { queue1.enqueue(arr1[i]) queue2.enqueue(arr2[i]) } console.log(resort(queue1,queue2));
2. 队列的应用
1. 实现广度优先搜索
2. 生产者-消费者模式
3. 缓存区(如键盘缓存区)
4. 优先级队列