队列数据结构

队列是遵循先进先出原则的一组有序的项。队列在尾部添加新元素,并从顶部移除元素

class Queue{
    constructor(){
        this.count = 0;//控制队列大小
        this.lowestCount = 0;//需要重队列前端删除,使用一个变量追踪第一个元素
        this.items = {};//使用对象存储元素更高效
    }
    
    //向尾部添加一个元素
    enqueue(element){
        this.items[this.count] = element;//将count作为items对象中的键
        this.count++;
    }
    
    //移除头部第一个元素
    dequeue(){
        if (this.isEmpty()){
            return undefind;
        }
        const result = this.items[this.lowestCount];
        delete this.items[lowestCount];
        this.lowestCount++;
        return result;
    }
    
    //返回队列第一个元素
    peek(){
        if (this.isEmpty()){
            return undefind;
        }
        return this.items[this.lowestCount];
    }
    
    //判断队列是否为空
    isEmpty(){
        return this.count - this.lowestCount === 0;
    }
    
    //返回队列大小
    size(){
        return this.count - this.lowestCount;
    }
    
    //清空队列
    clear(){
        this.items = {};
        this.count = 0;
        this.lowestCount = 0;
    }
    
    //toString方法
    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;
    }
    

使用Queue类

const queue = new Queue();
console.log(queue.isEmpty());//输出true
queue.enqueue('John'); 
queue.enqueue('Jack');
console.log(queue.toString()); // John,Jack
console.log(queue.size()); // 输出 2

双端队列数据结构

允许同时从前端和后端添加和移除元素的特殊队列

应用:存储一系列的撤销操作

创建 Deque 类

相同的内部属性和以下方法:isEmpty、clear、size 和 toString。

class Deque{
    constructor(){
        this.count = 0;//控制队列大小
        this.lowestCount = 0;//使用一个变量追踪第一个元素
        this.items = {};//使用对象存储元素更高效
    }
    
    //尾部添加一个元素
    addBack(element){
        this.items[this.count] = element;//将count作为items对象中的键
        this.count++;
    }
    
    //头部添加元素
    addFront(element){
        //情况一:这个双端队列是空的
        if (this.isEmpty()){
            this.addBack(element);
        //情况二:一个元素已经被从双端队列的前端移除
        }else if (this.lowestCount>0){
            this.lowestCount--;
            this.items[this.lowestCount] = element;
       }else{ //情况三:lowestCount 为 0
            for (let i = this.count; i>0; i--){
                this.items[i]= this.item[i-1];
            }//在所有的元素都完成移动后,第一位将是空闲状态,这样就可以用需要添加的新元素来覆盖它了
            this.count++;
            this.lowestCount = 0;
             this.items[0] = element;
        }
    }
    
    //移除尾部一个元素
    removeBack{
        if (this.isEmpty()){
            return undefind;
        }
        this.count--;
        const result = this.items[this.Count];
        delete this.items[this.Count]; 
        return result;
    }
    
    //移除头部第一个元素
    removeFront(){
        if (this.isEmpty()){
            return undefind;
        }
        const result = this.items[this.lowestCount];
        delete this.items[lowestCount];
        this.lowestCount++;
        return result;
    }
    
    //返回队列第一个元素
    peekFront(){
        if (this.isEmpty()){
            return undefind;
        }
        return this.items[this.lowestCount];
    }
    
    //返回队列最后一个元素
    peekBack(){
        if (this.isEmpty()){
            return undefind;
        }
        return this.items[this.Count-1];
    }
    
    //判断队列是否为空
    isEmpty(){
        return this.count - this.lowestCount === 0;
    }
    
    //返回队列大小
    size(){
        return this.count - this.lowestCount;
    }
    
    //清空队列
    clear(){
        this.items = {};
        this.count = 0;
        this.lowestCount = 0;
    }
    
    //toString方法
    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;
    }

使用 Deque 类

const deque = new Deque(); console.log(deque.isEmpty()); // 输出 true deque.addBack('John'); deque.addBack('Jack');
console.log(deque.toString()); // John, Jack deque.addBack('Camila');
console.log(deque.toString()); // John, Jack, Camila 
console.log(deque.size()); // 输出 3 
console.log(deque.isEmpty()); // 输出 false 
deque.removeFront(); // 移除 John
console.log(deque.toString()); // Jack, Camila 
deque.removeBack(); // Camila 决定离开 
console.log(deque.toString()); // Jack 
deque.addFront('John'); // John 回来询问一些信息 
console.log(deque.toString()); // John, Jack

使用队列和双端队列来解决问题

循环队列——击鼓传花游戏(hot potato)
function hotPotato(elementsList, num) { 
    const queue = new Queue(); // {1} 
    const elimitatedList = [];
    for (let i = 0; i < elementsList.length; i++) { 
        queue.enqueue(elementsList[i]); // 把里面的名字全都加入队列
   }
   while (queue.size() > 1) { 
        for (let i = 0; i < num; i++){
            queue.enqueue(queue.dequeue()); // {3}
        } 
        elimitatedList.push(queue.dequeue()); // {4} 
   } 
   return {
    eliminated: elimitatedList, winner: queue.dequeue() // {5}
    }; 
}
//从队列开头移 除一项,再将其添加到队列末尾(行{3}),模拟击鼓传花(如果你把花传给了旁边的人,你被 淘汰的威胁就立刻解除了)。一旦达到给定的传递次数,拿着花的那个人就被淘汰了(从队列中 移除——行{4})。最后只剩下一个人的时候,这个人就是胜者(行{5})。
双端队列——回文检查器

回文是正反都能读通的单词、词组、数或一系列字符的序列

function palindromeChecker(aString) { 
    if (aString === undefined || aString === null || (aString !== null && aString.length === 0)) { // {1} 
        return false;
} 
    const deque = new Deque(); // {2}
    const lowerString = aString.toLocaleLowerCase().split(' ').join(''); // {3} 
    let isEqual = true; 
    let firstChar, lastChar;
    for (let i = 0; i < lowerString.length; i++) { // {4}
        deque.addBack(lowerString.charAt(i));
    }
    while (deque.size() > 1 && isEqual) { // {5} 
        firstChar = deque.removeFront(); // {6} 
        lastChar = deque.removeBack(); // {7} 
        if (firstChar !== lastChar) { 
            isEqual = false; // {8}
        }
    }
    return isEqual; 
}

思考:JavaScript 任务队列

当我们在浏览器中打开新标签时,就会创建一个任务队列。这是因为每个标签都是单线程处
理所有的任务,称为事件循环。浏览器要负责多个任务,如渲染HTML、执行 JavaScript代码、 处理用户交互(用户输入、鼠标点击等)、执行和处理异步请求。如果想更多地了解事件循环, 可以访问 https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/。

 posted on 2020-11-16 13:57  chen_coder  阅读(107)  评论(0)    收藏  举报