3. 队列
队列是遵循先进先出原则的一组有序的项。
3.1 数据结构队列
class Queue{
constructor(){
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
enqueue(value){
this.items[this.count] = value;
this.count ++;
}
dequeue(){
if(this.isEmpty()){
return undefined;
}
const res = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount ++;
return res;
}
peek(){
if(this.isEmpty()){
return undefined;
}
return this.items[this.lowestCount];
}
isEmpty(){
return this.count - this.lowestCount === 0;
}
size(){
return this.count - this.lowestCount;
}
clear(){
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
toString(){
if(this.isEmpty()){
return '';
}
let objString = `${this.items[this.lowestCount]}`;
for(let i = this.lowestCount + 1; i < this.count; i ++){
objString = `${objString}, ${this.items[i]}`;
}
return objString;
}
}
3.2 双端队列
- 双端队列是一种允许我们同时从前端和后端添加和移出元素的特殊队列。
- 在计算机科学中,双端队列的一个常见应用是存储一系列撤销操作。
class Dequeue{
constructor(){
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
addFront(value){
if(this.isEmpty()){
this.addBack(value)
}else if(this.lowestCount > 0){
this.items[this.lowestCount - 1] = value;
this.lowestCount --;
}else{
for(let i = this.count; i > 0; i --){
this.items[i] = this.items[i - 1];
}
this.count ++;
this.items[0] = value;
this.lowestCount = 0;
}
}
addBack(value){
this.items[this.count] = value;
this.count ++;
}
removeFront(){
if(this.isEmpty()){
return undefined;
}
const res = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount ++;
return res;
}
removeEnd(){
if(this.isEmpty()){
return undefined;
}
const res = this.items[this.count - 1];
delete this.items[this.count - 1];
this.count --;
return res;
}
peekFront(){
if(this.isEmpty()){
return undefined;
}
return this.items[this.lowestCount];
}
peekEnd(){
if(this.isEmpty()){
return undefined;
}
return this.items[this.count - 1];
}
isEmpty(){
return this.count - this.lowestCount === 0;
}
size(){
return this.count - this.lowestCount;
}
toString(){
if(this.isEmpty()){
return '';
}
let objString = `${this.items[this.lowestCount]}`;
for(let i = this.lowestCount + 1; i < this.count; i ++){
objString = `${objString}, ${this.items[i]}`;
}
return objString;
}
}
3.3 应用
3.3.1 循环队列——击鼓传花游戏
class Queue{
constructor(){
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
enqueue(value){
this.items[this.count] = value;
this.count ++;
}
dequeue(){
if(this.isEmpty()){
return undefined;
}
const res = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount ++;
return res;
}
isEmpty(){
return this.count - this.lowestCount === 0;
}
size(){
return this.count - this.lowestCount;
}
}
function hotPotato(elementList, count){
const queue = new Queue()
const resList = [];
for(let i = 0; i < elementList.length; i ++){
queue.enqueue(elementList[i]);
}
while(queue.size() > 1){
for(let i = 0; i < count; i ++){
queue.enqueue(queue.dequeue());
}
resList.push(queue.dequeue())
}
return {
resList,
winner: queue.dequeue()
}
}
const ele = ['a', 'b', 'c', 'd', 'e'];
const res = hotPotato(ele, 7);
console.log(res);
3.3.2 回文检查器
class Dequeue{
constructor(){
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
addBack(value){
this.items[this.count] = value;
this.count ++;
}
removeFront(){
if(this.isEmpty()){
return undefined;
}
const res = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount ++;
return res;
}
removeEnd(){
if(this.isEmpty()){
return undefined;
}
const res = this.items[this.count - 1];
delete this.items[this.count - 1];
this.count --;
return res;
}
isEmpty(){
return this.count - this.lowestCount === 0;
}
size(){
return this.count - this.lowestCount;
}
}
function palindromeChecker(str){
if(str === undefined || str === null || (str !== null && str.length === 0)){
return false;
}
const qu = new Dequeue();
const arr = str.toLocaleLowerCase().split(' ').join('');
let isEqual = true;
let first, last;
for(let i = 0; i < arr.length; i ++){
qu.addBack(arr[i]);
}
while(qu.size() > 1 && isEqual){
first = qu.removeFront();
last = qu.removeEnd();
if(first != last){
isEqual = false;
}
}
return isEqual;
}
console.log(palindromeChecker('abam'));
3.4 JavaScript 任务队列
当我们在浏览器中打开新标签时,就会创建一个任务队列。
这是因为每个标签都是单线程处理所有的任务,称为事件循环。