也是对数组类似的线性数据结构加以限制魔改的一种数据结构!
区别于栈,栈好比是个一个口的容器,比如水杯子,进去出去的口只有一个,还是同一个口:栈顶!只不过,出去的顺序是先进后出,这里加以限制了。而且无法插入操作。
队列,跟栈类似,无法中间插入操作(优先级队列的操作更符合预编排,预留插槽的观念,而不是插入操作,只是预留好了优先级高的空位权限的理念而已。),也讲究顺序,只不过讲究先进先出的顺序。
队列,其实就是生活中的排队取钱,排队打饭。
栈,容器的命。队列是个流通通道,管道,讲究流动,讲究流动控制。
JS的任务队列
js队列其实听了很多了,在异步执行时,经常听到的词。JS执行是单线程的,但是浏览器是多线程的,浏览器可以用其他线程对多个异步操作进行定时,用事件轮询机制,不断看这些异步操作的计时器到了没,到了就把对应异步回调函数放到任务队列中。
任务队列中,先放进去的先被JS引擎执行。后面的需要等前面的执行完了,才能被执行。
cpu在多任务并行时,多线程的优化,也是有队列的控制参与的。
队列的特性
- 先进先出,也讲究顺序
- 两个口,前端进行删除,后端进行添加。
- 移除第一个元素,用数组很消耗性能,最好用链表。

//数组实现:class Queue {constructor(arr = []) {this.lists = arr;}//尾部新增enqueue(...lists) {lists.map(list=>this.lists.push(list));}//首部移除//这里是数组,其实这里的移除操作,会很消耗性能的。最佳方式是用链表。dequeue() {return this.lists.shift();}//返回队列中的第一个元素front() {return this.lists[0];}//空:isEmpty() {return this.lists.length === 0;}//个数:size() {return this.lists.length;}//转成字符串:toString(){return this.lists.reduce((a,b)=>a+ (a? ' <- ':'')+(''+b),'')}}const queue = new Queue([1,2,3])console.log(queue.toString(),queue.front(),);queue.enqueue(6)queue.enqueue(7,8,9)console.log(queue.dequeue(),queue);
优先级队列
看似跟队列的不可中间插入很矛盾的,,,
其实是预留好了权限空位的。
这种预编排,预留空位的设计,其实是为了包容队列的更广泛的应用场景。
生活中的队列,比如排队,说是没有插队,那是因为排队的规则是相对的。
优先级高的,就优先在前面。比如各种vip特权,老人孩子特权。高危病人特权!
计算机里的很多任务,如果傻瓜式地不允许插队,按着默认顺序在队列中执行,就是错的!因为不尊重人,无人性!人才是根本!
权限高:a,b,c,权限中:d,e,fa -> [权限高区...,d,e,f...权限中区,...权限低区][a,d,e,f,...]
优先级更倾向于,人性,规则!
上面说过,队列是个流通管道,控制任务的进出,一种可控的流水线理念!但是,这是机器的理念,人的理念是,人为可以控制任务的出去的结果!
为了不像数组一样不受限,需要一种规则。
当然,相对同等优先级的,不允许插队!
所以优先级出来了!
根据优先级,预留好插槽,插槽是逻辑上的插槽,而不是代码上的,代码里体现在逻辑上。
根据数据的优先级确定进入队列时的位置。
最根本的是:不一定先进先出,但是一定是按队列的位置从前端依次执行!
**
实现:2分法牛皮!
//优先级队列的实现://默认的传入数据为{data:xxx,priority:1}//priority的值不可重复,递增式的数字类型!//初始默认的arr参数,顺序遵循priority的order。class PriorityQueue extends Queue {enqueue(...lists) {lists.map(list => {if (this.lists.length === 0 ||this.lists[this.lists.length - 1].priority > list.priority) return this.lists.push(list);//傻瓜式线性遍历:if (this.lists.length < 6) {let res;for (let i = 0; i < this.lists.length; i++) {if (this.lists[i].priority < list.priority) {this.lists.splice(i, 0, list);res = true;break;}}} else {//放纵一下,尝试用2分发搞的:let getIndex = (length) =>// length % 2 === 0 ? [length / 2 - 1, length / 2] :Math.round(length / 2) - 1;let length = this.lists.length;let index = getIndex(length);let max, min;while (index) {if (min && max && min + 1 === max) {this.lists.splice(max - 1, 0, list);return index = null;}const {priority} = this.lists[index];// console.log("indss:", priority, index, "dd", min, max);if (priority > list.priority) {min = min && min > index + 1 ? min : index + 1;length = min +(max|| this.lists.length);index = getIndex(length);// console.log('in', index,'pri:', priority);} else {const {priority} = this.lists[index - 1];// console.log('in2222', index,'pri:', priority);if (priority > list.priority) {this.lists.splice(index, 0, list);index = null;} else {max = max && max < index ? max : index;index = getIndex(max);}// console.log('in2', index,'pri:', priority);}}}});}}const pq = new PriorityQueue([{data: 1, priority: 300},{data: 1, priority: 200},{data: 1, priority: 100},{data: 1, priority: 50},{data: 1, priority: 25},{data: 1, priority: 12},{data: 1, priority: 6}]);pq.enqueue({data: 2, priority: 40});pq.enqueue({data: 2, priority: 30},{data: 2, priority: 400},{data: 2, priority: 7},{data: 2, priority: 150});console.log(pq, 0);
