JS 数据结构与算法 → 队列结构

目录

1、队列是个啥?

2、队列的常见操作

3、封装队列结构

4、队列的使用

5、队列结构的应用 — 击鼓传花算法

6、队列结构的应用 — 优先级队列


1、队列是个啥?

队列(Queue),它是一种受限的线性表,先进先出(FIFO First In First Out),受限之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。FIFO(First In First Out)标识先进队的元素,第一个出队,类似于电影院的取票口,先到的人先取票。向一个队列插入新元素又称作进队、入队,它是把新元素放到队列的末尾,使之成为新的队尾元素;从一个队列删除元素又称作出队,它是把队首元素删除掉,使其相邻的元素成为新的队首元素。示意图如下:
 

2、队列的常见操作

方法说明
enqueue()向队列尾部添加一个(或多个)新的项
dequeue()移除队列的第一(即排在队列最前面的)项,并返回被移除的元素
front()返回队列中第一个元素,也将是最先被移除的元素
isEmpty()如果队列中不包含任何元素,返回true,否则返回false
size()返回队列包含的元素个数,与数组的length属性类似
toString()将队列中的内容,转成字符串形式

3、封装队列结构

基于数组的方式实现栈结构,在封装的 Queue() 类的原型上添加队列的一些方法。

function Queue() {	// 封装队列类
    var items = [];
    
    // 队列操作的方法
    //1.将元素加入到队列中
    Queue.prototype.enqueue = function(element){
        this.items.push(element);
    }
    //2.从队列中删除前端元素
    Queue.prototype.dequeue = function () {
        return this.items.shift();
    }
    //3.查看队列前端的元素
    Queue.prototype.front = function () {
        return this.items[0];
    }
    //4.查看队列是否为空
    Queue.prototype.isEmpty = function () {
        return this.items.length == 0;
    }
    //5.查看队列中元素的个数
    Queue.prototype.size = function () {
        return this.items.length;
    }
    //6.查看队列中元素的个数
    Queue.prototype.toString = function(){	
        var resultString = '';
        for(var i in this.items){
            resultString += this.items[i] + '-'
        }
        return resultString;
    }
}

4、队列的使用

基于刚才封装的队列,进行一些队列的基本操作。

// 创建队列对象
var queue = new Queue();

// 在队列中添加元素
queue.enqueue("abc");
queue.enqueue("bcd");
queue.enqueue("cde");

// 查看一下队列前端元素
alert(queue.front());      //abc

// 查看队列是否为空和元素个数
alert(queue.isEmpty());    //false
alert(queue.size());       //3

// 从队列中删除元素
alert(queue.dequeue());    //abc
alert(queue.dequeue());    //bcd
alert(queue.dequeue());    //cde

5、队列结构的应用 — 击鼓传花算法

游戏规则:几个朋友围成一圈,开始数数,数到某个数字的人自动淘汰,然后从下一个人继续进行同样的规则,最后剩下的这个人会获得胜利,请问最后剩下的是原来在哪一个位置上的人?

(1)主要原理:创建一个队列,将所有人放入队列中,然后通过循环将队列中的每个元素出队,如果这个元素不是第 num 个数,则再将其入队,重复循环,直至队列剩下一个元素时,将其输出,这就是最终获胜的人。

(2)代码实现

// 实现击鼓传花的函数
function passGame(nameList, num) {
    // 1.创建一个队列,并且将所有的人放在队列中
    var queue = new Queue();

    //2.通过for循环,将nameList中的人放在队列中
    for (var i=0; i <nameList.length; i++) {
        queue.enqueue(nameList[i]);
    }

    //3.寻找最后剩下的人
    while (queue.size() > 1) {
        // 将前num-1中的人, 都从队列的前端取出放在队列的后端
        for (var i=0; i <num-1; i++) {
            queue.enqueue(queue.dequeue());
        }

        // 将第num个人, 从队列中移除
        queue.dequeue();
    }

    //4.获取剩下的一个人
    alert(queue.size());    //1
    var endName = queue.dequeue();
    alert("最终留下来的人:" + endName);

    // 4.获取该人在队列中的位置
    return nameList.indexOf(endName);
}
// 验证结果
var names = ['AAA','BBB','CCC','DDD','EEE'];
var index = passGame(names, 7);     //数到8的人淘汰
alert("最终位置:" + index);

6、队列结构的应用 — 优先级队列

(1)优先级队列的特点:普通的队列插入一个元素,数据会被放在后端,并且需要前面所有的元素都处理完成后才会处理当前的数据。但是优先级队列,在插入一个元素的时候会考虑该数据的优先级,在插入之前,先和其他数据优先级进行比较,比较完成后,可以得出这个元素在队列中正确的位置。

是不是不太好理解,生活中有优先级队列的例子,比如老年人和孕妇(或带小孩的妇女)坐车时享有高于其他乘客的优先级,再比如头等舱和商务舱乘客的优先级要高于经济舱乘客。

(2)代码实现

//封装优先级队列
function PriorityQueue(){
    //在PriorityQueue内部重新创建一个类,可以理解成内部类
    function QueueElement(element,priority){
        this.element = element;
        this.priority = priority;
    }
    //封装属性
    this.items = [];
	
    //1.比较元素的有限度,并将其入队到相应的位置
    PriorityQueue.prototype.enqueue = function(element,priority){
        //1.创建QueueElement对象
        var queueElement = new QueueElement(element,priority);
		
        //2.判断队列是否为空
        if(this.items.length == 0){
            this.items.push(queueElement)
        }else{
            var added = false;
            for (var i=0;i<this.items.length;i++) {
                if(queueElement.priority < this.items[i].priority){
                    this.items.splice(i,0,queueElement)
                    added = true;
                    break;
                }
            }
            if(!added){
                this.items.push(queueElement)
            }
        }
    }
    //2.从队列中删除前端元素
    PriorityQueue.prototype.dequeue = function () {
        return this.items.shift();
    }
    //3.查看队列前端的元素
    PriorityQueue.prototype.front = function () {
        return this.items[0];
    }
    //4.查看队列是否为空
    PriorityQueue.prototype.isEmpty = function () {
        return this.items.length == 0;
    }
    //5.查看队列中元素的个数
    PriorityQueue.prototype.size = function () {
        return this.items.length;
    }
    //6.查看队列中元素
    PriorityQueue.prototype.toString = function(){	
        var resultString = '';
        for(var i in this.items){
            resultString += this.items[i].element + '-' + this.items[i].priority + '-' 
        }
        return resultString;
    }
}

(3)测试代码

//测试代码
var pq = new PriorityQueue();
pq.enqueue('abc','111');
pq.enqueue('bcd','115');
pq.enqueue('cde','110');
alert(pq);        //cde-110-abc-111-bcd-115-
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值