JavaScript实现队列

269 阅读5分钟

0 队列

队列是遵循先进先出(First In First Out,也称为先来先服务)原则的一组有序的项。

  • 队列在尾部添加新元素,并从顶部移除元素。
  • 最新添加的元素必须排在队列的末尾。

现实中

地铁排队 银行排队

1 es5实现

定义:

    //队列类
    //特点:先进先出
    function Queue(){
        //存储队列中的元素
        let items = [];

        //队列的方法
        //向队列尾部添加一个新的元素
        this.enqueue = function ( ele ) {
            items.push(ele);
        }

        // 移除队列的第一个元素,并返回被移除的元素
        this.dequeue = function (  ) {
            return items.shift();
        }
        //返回队列中第一个元素
        this.front = function (  ) {
            return items[0];
        }

        //判断队列是否有元素,没有元素,返回true,有元素,返回false
        this.isEmpty = function (  ) {
            return items.length==0;
        }
        //返回队列中元素的个数
        this.size = function (  ) {
            return items.length;
        }

        //打印队列里的元素
        this.print = function (  ) {
            console.log ( items.toString () );
        }
    }

验证:

    //实例化一个队列
    let queue1 = new Queue();
    console.log ( queue1.isEmpty () );//开始队列是空的,输出true
    
    //向队列中添加三个元素
    queue1.enqueue("John");
    queue1.enqueue("jack");
    queue1.enqueue("Aimer");
    
    //打印队列的元素
    queue1.print();//John,jack,Aimer
    console.log ( queue1.size () );//3
    console.log ( queue1.isEmpty () );//false
    queue1.dequeue();//移除队列的第一个元素John
    queue1.dequeue();//移除队列的第一个元素jack
    queue1.print();//Aimer

2 es6实现

定义:

//用ECMAScript6语法实现的Queue类
    let Queue2 = (function (  ) {
        //WeakMap可以存储键值对,其中键是对象,值可以是任意数据类型
        const  items = new WeakMap();
        class Queue2 {
            constructor (){
                items.set(this,[]);
            }
            enqueue(ele){
                let q = items.get(this);
                q.push(ele);
            }
            dequeue(){
                let q = items.get(this);
                return q.shift();
            }
            front () {
                let q = items.get(this);
                return q[0];
            }
            isEmpty(){
                let q = items.get(this);
                return q.length==0;
            }
            size(){
                let q = items.get(this);
                return q.length;
            }
            print(){
                let q = items.get(this);
                console.log ( q.toString () );
            }
        }
        return Queue2;
    }());

验证:

    let queue2 = new Queue2();
    console.log ( queue2.isEmpty () );//开始队列是空的,输出true

    //向队列中添加三个元素
    queue2.enqueue("John");
    queue2.enqueue("jack");
    queue2.enqueue("Aimer");

    // //打印队列的元素
    queue2.print();//John,jack,Aimer
    console.log ( queue2.size () );//3
    console.log ( queue2.isEmpty () );//false
    queue2.dequeue();//移除队列的第一个元素John
    queue2.dequeue();//移除队列的第一个元素jack
    queue2.print();//Aimer

3 优先队列

优先队列:元素的添加和移除是基于优先级的。 一个现实的例子就是机场登机的顺序。头等舱和商务舱乘客的优先级要高于经济舱乘客

实现方法::添加的元素时,设置优先级,然后在正确的位置添加元素 规定:优先级顺序由大到小,对应数字1,2,3,..........., 其中1的优先级最大,数字越大,优先级越小

3.1 最小优先队列

优先级的值越小,优先级别越高,放到队列的最前面

    //以下为最小优先队列,因为优先级的值较小的元素被放置在队列最前面(1代表更高的优先级)
    function PriorityQueue (  ) {
        let items = [];
        function QueueElement (element,priority  ) {
            this.element = element;
            this.priority = priority;
        }

        this.enqueue = function ( element,priority ) {
            let queueEle = new QueueElement(element,priority);
            let isAdd = false;
            for ( let i = 0 ;i<items.length;i++ ) {
                //找到优先数字比当前元素大的(优先级比当前元素低),就将当前元素插入该元素前面
                if(queueEle.priority<items[i].priority){
                    items.splice(i,0,queueEle);
                    isAdd = true;
                    break;
                }
            }
            //如果所有元素都比当前元素优先级高,当前元素就添加到末尾
            if(isAdd==false){
                items.push(queueEle);
            }
        }
        this.print = function(){
            for (let i=0; i<items.length; i++){
                // for(let key in items[i]){
                //   console.log ( key+"="+ items[i][key] );
                // }
                console.log(items[i].element+","+items[i].priority);
            }
        };

        // 移除队列的第一个元素,并返回被移除的元素
        this.dequeue = function (  ) {
            return items.shift();
        }
        //返回队列中第一个元素
        this.front = function (  ) {
            return items[0];
        }

        //判断队列是否有元素,没有元素,返回true,有元素,返回false
        this.isEmpty = function (  ) {
            return items.length==0;
        }
        //返回队列中元素的个数
        this.size = function (  ) {
            return items.length;
        }

    }

验证:

    let pQueue2 = new PriorityQueue();
    console.log ( pQueue2.isEmpty () );//开始队列是空的,输出true

    //向队列中添加三个元素
    pQueue2.enqueue("John",2);
    pQueue2.enqueue("jack",3);
    pQueue2.enqueue("ccc",3);
    pQueue2.enqueue("Aimer",1);

    // //打印队列的元素
    pQueue2.print();//John,jack,Aimer
    console.log ( pQueue2.size () );//3
    console.log ( pQueue2.isEmpty () );//false
    pQueue2.dequeue();//移除队列的第一个元素 Aimer
    pQueue2.dequeue();//移除队列的第一个元素k John
    pQueue2.print();//jack,3

例子:循环队列-击鼓传花

循环队列

  1. 得到一份名单,把里面的名字全都加入队列

  2. 给定一个数字,然后迭代队列。从队列开头移除一项,再将其添加到队列末尾 2.1 模拟击鼓传花(如果你把花传给了旁边的人,你被淘汰的威胁立刻就解除了)。 一旦传递次数达到给定的数字,拿着花的那个人就被淘汰了(从队列中移除)

  3. 最后只剩下一个人的时候,这个人就是胜者

过程图示:

击鼓传花实现:

    function hotPotato(nameList,num){
        let queue = new Queue();
        // 1.得到一份名单,把里面的名字全都加入队列
        for ( let i = 0 ;i<nameList.length;i++ ) {
            queue.enqueue(nameList[i]);
        }

        let taotai = "";//存储淘汰者
        //队列的元素个数大于1个,一直运行游戏
        while ( queue.size()>1 ){
            // //模拟击鼓传花
            // 2.给定一个数字,然后迭代队列。从队列开头移除一项,再将其添加到队列末尾
            for ( let i = 0 ;i<num;i++ ) {
                queue.enqueue(queue.dequeue());
            }
            //被淘汰者
            taotai = queue.dequeue();
            console.log ( taotai + "被淘汰,从队伍中移除" );
        }
        //返回获胜者
        return queue.dequeue();

    }

    //验证:
    let names = ['John','Jack','Camila','Ingrid','Carl'];
    let winner = hotPotato(names, 2);
    console.log('The winner is: ' + winner);

使用到队列类:

    //队列类
    //特点:先进先出
    function Queue(){
        //存储队列中的元素
        let items = [];

        //队列的方法
        //向队列尾部添加一个新的元素
        this.enqueue = function ( ele ) {
            items.push(ele);
        }

        // 移除队列的第一个元素,并返回被移除的元素
        this.dequeue = function (  ) {
            return items.shift();
        }
        //返回队列中第一个元素
        this.front = function (  ) {
            return items[0];
        }

        //判断队列是否有元素,没有元素,返回true,有元素,返回false
        this.isEmpty = function (  ) {
            return items.length==0;
        }
        //返回队列中元素的个数
        this.size = function (  ) {
            return items.length;
        }

        //打印队列里的元素
        this.print = function (  ) {
            console.log ( items.toString () );
        }
    }