zoukankan      html  css  js  c++  java
  • JavaScript数据结构和算法----队列

    前言

      队列和栈很像,只是用了不同的原则。队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素。最新添加的元素必须必须排队在队列的,末尾。可以想象食堂排队买饭的样子。

    一、创建队列

      1、创建一种数据结构来保存队列里面的数据,这里选择数组
      2、声明一些栈的方法
      enqueue(element(s)) : 添加一个或一些元素到队列的末尾
      dequeue() : 移除队列第一个的元素(就是排队在最前面的),同时返回被移除的元素。
      front() : 返回队列第一个的元素(最先被添加的),仅仅是返回,不做任何修改。
      isEmpty() : 如果队列里面没有任何元素就返回true,否者为false。
      clear() : 清除队列里面的元素。
      size() : 返回队列里面的个数。

    function Queue(){
        
        var items = [];
    
        this.enqueue= function(element){
            items.push(element);
        }
    
        this.dequeue = function(){
            return items.shift();
        }
    
        this.front = function(){
            return items[0];
        }
    
        this.isEmpty = function(){
            return items.length == 0;
        }
    
        this.clear = function(){
            items = [];
        }
    
        this.size = function(){
            return items.length;
        }
    
        this.print = function(){
            console.log(items.toString());
        } 
    }
    
    var queue = new Queue();
    console.log(queue.isEmpty());
    queue.enqueue('leaf');
    queue.enqueue('jack')
    console.log(queue.size());
    console.log(queue.dequeue());
    console.log(queue.isEmpty());
    console.log(queue.size());
    

      

    二、循环队列 --击鼓传花游戏

    var nameList = ['leaf', 'jack', 'jef', 'rose', 'red', 'mandy', 'hardy', 'mark' ];
    function cyclicGame(nameList){
        
        var queue = new Queue(),
            len = nameList.length;
    
        for(var i=0 ; i<len; i++){
            queue.enqueue(nameList[i]);
        }
    
        var weedOutName = '';
        while(queue.size()>1){
            for(var i=0; i<Math.floor(Math.random()*len); i++){
                queue.enqueue(queue.dequeue());//把第一个删除了添加后面
            }
            weedOutName = queue.dequeue();
            console.log(weedOutName + '第'+ (len-queue.size()) +'轮被淘汰了!');
        }
    
        return console.log(queue.dequeue() + '是最后的胜利者!');//最后一个元素,胜利者
    
    }
    
    cyclicGame(nameList);
    

      

    三、事件队列管理

      JS的执行环境是单线程的,一次只能完成一个任务,其任务的调度方式就是排队,这就在医院挂号一样,前面的那个人没有搞定,你就只能站在后面排队等着。在事件队列中加一个延时,这样的问题便可以得到缓解,下面用代码模拟这个情景。

    var Queue = {
        //保存队列信息
        items : [],
        //添加到队列
        enqueue : function(executeQueue){
            //添加到队列,如果不是函数或者数字的不处理
            if(!/function|number/.test(typeof executeQueue)){
                return;
            }
    
            Queue.items.push(executeQueue);
            //返回自身的引用
            return Queue;
        },
        //执行队列
        executeQueue : function(){
            //删除队列第一个元素并返回它
            var dequeue = Queue.items.shift();
            
            //如果队列为空的,直接返回
            if(!dequeue){
                return;
            }
    
            //如果是函数,直接执行,然后继续执行executeQueue
            if(typeof dequeue === "function"){
                dequeue();
                Queue.executeQueue();
                return;
            }
    
            //如果是数字,该数字作为延迟的时间, 延迟executeQueue
            setTimeout(function(){
                Queue.executeQueue();
                //console.log(dequeue);
            }, dequeue);
        }
    };
    
    //测试
    Queue
    //添加事件
    .enqueue(function(){
        console.log('3秒之后执行第1个');
    })
    .enqueue(3000) 
    .enqueue(function(){
        console.log('3秒之后执行第2个');
      })
    .enqueue(3000)
    .enqueue(function(){
        console.log('3秒之后执行第3个');
      })
    //执行事件
    .executeQueue();
    

      

    四、看一个栗子--实现layMan的功能

    实现:

    lazyMan('leaf').eat('苹果').sleep(2).eat('雪梨').sleep(3).eat('香蕉')
    

    采用事件队列的思想,根据队列的先后循序执行;

    function LazyMan(name) {
            if(this.constructor !== LazyMan) {
              return new LazyMan(name)
            }
            //保存队列
            this.tasks = [];   
            var self = this;
            var fn =(function(n){
                var name = n;
                return function(){
                    console.log("Hi! This is " + name + "!");
                    self.next();
                }
            })(name);
            this.tasks.push(fn);
    
            //执行队列里面第一个事件
            setTimeout(function(){
                self.next();
            }, 0); 
        }
    
        /* 事件调度函数 */
        LazyMan.prototype.next = function() { 
            var fn = this.tasks.shift();
            fn && fn();
        }
    
        LazyMan.prototype.eat = function(name) {
            var self = this;
            var fn =(function(name){
                return function(){
                    console.log("Eat " + name + "~");
                    self.next()
                }
            })(name);
            this.tasks.push(fn);
            return this; // 实现链式调用
        }
        LazyMan.prototype.sleep = function(time) {
            var self = this;
            var fn = (function(time){
                return function() {
                    setTimeout(function(){
                        console.log("Wake up after " + time + "s!");
                        self.next();
                    }, time * 1000);
                }
            })(time);
            this.tasks.push(fn);
           return this;
        }
        LazyMan.prototype.sleepFirst = function(time) {
            var self = this;
            var fn = (function(time) {
                return function() {
                    setTimeout(function() {
                        console.log("Wake up after " + time + "s!");
                        self.next();
                    }, time * 1000);
                }
            })(time);
            this.tasks.unshift(fn);
            return this;
        }
        /* 封装 */
        function lazyMan(name){
            return new LazyMan(name);
        }
    
       //调用
        lazyMan('leaf').eat('苹果').sleep(2).eat('雪梨').sleep(3).eat('香蕉')
    

      

      

  • 相关阅读:
    移动混合开发
    H5嵌入APP后,原生APP与H5之间交互
    移动混合开发的 JSBridge
    CSS3中transition和animation区别的理解
    git 回滚到指定版本并推送到远程分支
    李刘玉前端开发简历
    vue+axios 前端实现登录拦截(路由拦截、http拦截)
    移动端bug
    隐藏滚动条
    flex布局中子元素宽度失效的问题
  • 原文地址:https://www.cnblogs.com/leaf930814/p/7225833.html
Copyright © 2011-2022 走看看