数据结构(2)队列

127 阅读5分钟

队列结构

队列(Queue),是一种运算受限的线性结构,遵循先进先出(FIFO First In First Out)原则,表示先进入队的元素先出队。

受限之处在于只允许在表的前端(front队首)进行删除操作,而在表的后端(rear队尾)进行插入操作。元素从队首出队,从队尾入队。

image.png

封装一个类实现队列的结构

队列常见的操作

  • enqueue(element):向队列尾部添加一个(或多个)新的项。
  • dequeue():移除队列的第一(即排在队列最前面的)项,并返回被移除的元素。
  • front():返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。
  • isEmpty():如果队列中不包含任何元素,返回true,否则返回false
  • size():返回队列包含的元素个数,与数组的length属性类似。
//ES6封装队列
class Queue{
    constructor(){
        //队列容器,开辟空间保存队列元素
        this.item=[];
    };
    //原型方法
    //队尾入队,即从数组末尾添加元素
    enqueue(el){
        this.item.push(el);
    };
    //队首出队,即删除数组的第一个元素
    outqueue(){
        return this.item.shift();
    };
    //返回队首元素
    front(){
        return this.item[0];
    };
    //判断队列是否为空
    isEmpty(){
        if(this.item.length==0){
            //队列容器:数组的长度为0表示容器中没有元素是空的就返回true
            return true;
        }else{
            return false;
        }
    };
    //返回元素的个数
    size(){
        return this.item.length;
    }
};

队列的应用

案例:击鼓传花的小游戏,将元素依次排数从1到3,排的3的元素淘汰。依次类推直到只剩下一个元素就是胜者结束游戏。

代码思路:将队列的元素从队首开始排数,队首的第一个元素是1,第二个元素是2,第三个元素是3,然后是3的第三个元素直接出队,排数为1,2的第一个元素以及第二个元素先从队首出队再从队尾入队。又重新从队首的第一个元素开始依次排数为1,2,3,依次类推直到队列中只有一个元素就结束。

function communicationFlower(arr) {
            // 1.创建队列
            let queueobj = new Queue();
            // 将形参接收的数组中保存的元素依次入队
            arr.forEach(el => {
                queueobj.enqueue(el);
            })
            //2.开始计数
            //计数结束条件是队列容器中只有一个元素,即队列的长度等于1,queueobj.size()=1时而queueobj.size()> 1做布尔判定为false就会退出while循环
            //计数变量从1开始
            let count = 1;
            while (queueobj.size() > 1) {
                //while循环中当count==3时队首元素直接出队,count为1或2时队首元素先出队再入队
                if (count < 3) {
                    //队首元素先出队
                    let firstele = queueobj.outqueue();
                    //队首元素再入队
                    queueobj.enqueue(firstele);
                    //计数加1
                    count++;
                } else {
                    //count==3时count < 3就是false执行else语句,队首元素直接出队
                    queueobj.outqueue();
                    //从1开始重新计数
                    count = 1;
                }
            }
            //while循环结束,队列容器中只有一个元素,该元素就是胜者,posistion代表它在原来数组中的索引
            return { winner: queueobj.front(), posistion: arr.indexOf(queueobj.front()) }
        }
let arr = ["gloria", "phm", "tara", "jess", "jzx", "xwlb"];
console.log(communicationFlower(arr));

image.png

优先级队列

上诉表示普通的队列,队列中元素的处理顺序和插入的顺序密切相关。而优先级队列是队列中元素的处理顺序和插入顺序无关,和元素本身的优先级有关系。

实现优先级队列的实现主要有两方面需要考虑:

    1. 封装元素和优先级放在一起
    1. 添加元素时,将当前的优先级和队列中已经存在的元素优先级进行比较,以获得自己正确的位置

封装优先级队列

该封装的类表示传入的数字越小,优先级越高,element是传入的元素的, priority是传入元素的优先级,越小优先级越高。

 class QueueElement {
            constructor() {
                this.item = [];
            }
            enqueue(element, priority) {
                //创建新节点
                let newobj = { element, priority };
                //如果元素是第一个被加进来的,之前队列是空队列元素直接加入数组中即可,非空队列,需要循环队列将当前的优先级和队列中已经存在的元素优先级进行比较
                if (this.item.length == 0) {
                    //空队列
                    this.item.push(newobj);
                } else {
                    //非空队列
                    //循环队列
                    let flag=true;
                    for (let j = 0; j < this.item.length; j++) {
                        //将新元素与队列元素依次比较优先级
                        // 注意: 此处数字越小, 优先级越高
                        if (newobj.priority < this.item[j].priority) {
                            //新元素优先级大于某个元素就是传入的数字priority小于数组中元素的数字priority, 就将新元素插入到某个元素的位置,将其他元素依次向后移动.

                            /*splice(index,length,增加的元素1,增加的元素2,增加的元素N)
                            表示从index开始删除length个元素,并从index开始新增元素1~N
                            返回被删除的元素组成的数组*/
                            this.item.splice(j, 0, newobj);//表示在j所在的位置删除0个元素,添加一个newobj新元素。实现了新元素优先级大于某个元素就是传入的数字priority小于数组中元素的数字priority, 就将新元素插入到某个元素的位置,将其他元素依次向后移动
                            flag=false;
                            //优先级对比完后表示插入成功退出for循环
                            break;
                        }
                    }
                    // 遍历完所有的元素,所有元素的优先级都大于新插入的元素时,新元素就插入到最后
                    if(flag){
                        //当flag为true表示遍历完所有的元素优先级都比新元素高,遍历时则没有进入if循环就未执行flag=false;flag就为true,就执行if语句将新元素插入到最后
                        //当flag为false时表示遍历元素时新元素优先级大于某个元素,遍历时进入if循环执行了flag=false;则不再执行if语句将新元素插入到最后
                        this.item.push(newobj);
                    }
                }
            }
            // 删除元素的方法
            dequeue() {
                return items.shift()
            }

            // 获取前端的元素
            front() {
                return this.item[0]
            }

            // 查看元素是否为空
            isEmpty() {
                return this.item.length == 0
            }

            // 获取元素的个数
            size() {
                return this.item.length
            }
        }