数据结构(队列实现篇)

在数据结构与算法中,队列queue是一种受限的线性储存结构,特殊之处在于它只允许在表的前端front进行删除操作,而在表的后端rear进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。遵循先进先出FIFO的规则。

队列结构示意图

队列结构使用

生活中很多地方使用到队列,例如医院门诊看病就是按挂号的号数来排队就诊;公司里面的打印机是按文件发送的顺序进行打印。

在编程中,队列常用作消息发送。例如消息发送队列。待发送的消息依次入队列,待一个消息出队列发送完毕,才会进行下一个消息出队列进行发送。

实现普通队列结构的功能
  • push(element):push是入队列操作,其中element是需要进队列的元素,返回操作成功与否布尔值。
  • shift():shift移除队列front元素操作,返回移除的移除元素。
  • size():获取栈中的队列元素数量,返回一个数字。
  • isEmpty():判断队列是否为空,返回一个布尔值。
  • peek():返回队头元素,但不移除栈顶元素。
  • bottom():返回队尾元素。
  • clear():清除所有队列元素,返回操作成功与否布尔值。
进队列与出队列流程

ES6 队列结构代码
    class Queue{
    	constructor(){
    		this.lists = [];
    	}
    	size(){
    		return this.lists.length;
    	}
    	isEmpty(){
    		return this.lists.length === 0;
    	}
    	peek(){
    		return this.lists[0];
    	}
    	bottom(){
    		const topIndex = this.size() -1;
    		return this.lists[topIndex];
    	}
    	push(element){
    		this.lists.push(element);
    		return true;
    	}
    	shift(){
    		return this.lists.shift();
    	}
    	clear(){
    		this.lists = [];
    		return true;
    	}
    	toString(){
    		let result = "";
    		this.lists.forEach(value=>{
    			result = result + ""+value;
    		});
    		return result;
    	}
    }
复制代码
ES5 队列结构代码

通过ES5把功能函数可以绑定在对象的实例上,也可以把功能函数加在函数的原型链上

    function Queue(){
    	this.lists = [];
    }
    Queue.prototype.push = function(element){
    	this.lists.push(element);
    	return true;
    }
    Queue.prototype.shift = function(){
    	return this.lists.shift();
    }
    Queue.prototype.clear = function(){
    	this.lists = [];
    	return true;
    }
    // 返回队头元素
    Queue.prototype.peek = function(){
    	return this.lists[0];
    }
    Queue.prototype.size = function(){
    	return this.lists.length;
    }
    Queue.prototype.isEmpty = function(){
    	return this.lists.length === 0;
    }
    Queue.prototype.bottom = function(){
    	var topIndex = this.size() -1;
    	return this.lists[topIndex];
    }
    Queue.prototype.toString = function(){
    	var result = "";
    	for(var i=0;i<this.lists.length;i++){
    		result = result + '' +this.lists[i];
    	}
    	return result;
    }
复制代码
实现优先队列结构的功能

上面实现的是普通队列情况,在日常生活中总遇到需要紧急处理的情况,例如银行VIP客户,急诊室危急病人,紧急文件。这时候需要优先处理这种情况。

优先队列和普通队列的不同主要在优先队列的每一个元素都具有一个权值,代表该元素的优先权大小。还有就是根据权值大小插入队列之中。

ES6 最大优先队列结构代码
    class Node {
        constructor(element, prority) {
            this.element = element;
            this.prority = prority;
        }
    }
    class Queue {
        constructor() {
            this.lists = [];
        }
        size() {
            return this.lists.length;
        }
        isEmpty() {
            return this.lists.length === 0;
        }
        peek() {
            return this.list[0];
        }
        bottom() {
            const topIndex = this.size() - 1;
            return this.lists[topIndex];
        }
        //插入队列
        append(node) {
            //当队列为空时
            if (!this.lists.length) {
                this.lists.push(node);
                return true;
            } else {
               for(let i=0;i<this.lists.length;i++){
                   if(this.lists[i]["prority"] < node.prority){
                       this.lists.splice(i,0,node);
                       return true;
                   }
               }
               this.lists.push(node);
            }
        }
        shift() {
            return this.lists.shift();
        }
        clear() {
            this.lists = [];
            return true;
        }
        toString() {
            let result = "";
            this.lists.forEach(value => {
                result = result + "" + value;
            });
            return result;
        }
    }
    const q = new Queue();
    q.append(new Node(1, 1));
    q.append(new Node(2, 2));
    q.append(new Node(5, 3));
    q.append(new Node(4, 2));
    console.log(JSON.stringify(q));
复制代码
ES5 最大优先队列结构代码

通过ES5把功能函数可以绑定在对象的实例上,也可以把功能函数加在函数的原型链上

    function Node(element,prority){
	this.element = element;
	this.prority = prority;
    }
    function Queue(){
    	this.lists = [];
    }
    Queue.prototype.append = function(node){
    	//当队列为空时
    	if(this.lists.length == 0){
    		this.lists.push(node);
    		return true;
    	}
    	
    	for(var i=0;i<this.lists.length;i++){
    		if(node.prority > this.lists[i]["prority"]){
              this.lists.splice(i,0,node);
              return true;
            }
    	}
    	this.lists.push(node);
    	
    }
    Queue.prototype.shift = function(){
    	return this.lists.shift();
    }
    Queue.prototype.clear = function(){
    	this.lists = [];
    	return true;
    }
    // 返回队头元素
    Queue.prototype.peek = function(){
    	return this.lists[0];
    }
    Queue.prototype.size = function(){
    	return this.lists.length;
    }
    Queue.prototype.isEmpty = function(){
    	return this.lists.length === 0;
    }
    Queue.prototype.bottom = function(){
    	var topIndex = this.size() -1;
    	return this.lists[topIndex];
    }
    Queue.prototype.toString = function(){
    	var result = "";
    	for(var i=0;i<this.lists.length;i++){
    		result = result + '' +this.lists[i];
    	}
    	return result;
    }
复制代码
循环队列结构图

循环队列就是把队头元素出队列后,再入队列。击鼓传花就是用到了循环队列的原理

循环队列代码

循环队列主要实现代码如下

  class SqQueue {
	constructor(length) {
		this.queue = new Array(length + 1)
		// 队头
		this.first = 0
		// 队尾
		this.last = 0
		// 当前队列大小
		this.size = 0
	}
	enQueue(item) {
		// 判断队尾 + 1 是否为队头
		// 如果是就代表需要扩容数组
		// % this.queue.length 是为了防止数组越界
		if (this.first === (this.last + 1) % this.queue.length) {
			this.resize(this.getLength() * 2 + 1)
		}
		this.queue[this.last] = item
		this.size++
		this.last = (this.last + 1) % this.queue.length
	}
	deQueue() {
		if (this.isEmpty()) {
			throw Error('Queue is empty')
		}
		let r = this.queue[this.first]
		this.queue[this.first] = null
		this.first = (this.first + 1) % this.queue.length
		this.size--
		// 判断当前队列大小是否过小
		// 为了保证不浪费空间,在队列空间等于总长度四分之一时
		// 且不为 2 时缩小总长度为当前的一半
		if (this.size === this.getLength() / 4 && this.getLength() / 2 !== 0) {
			this.resize(this.getLength() / 2)
		}
		return r
	}
	getHeader() {
		if (this.isEmpty()) {
			throw Error('Queue is empty')
		}
		return this.queue[this.first]
	}
	getLength() {
		return this.queue.length - 1
	}
	isEmpty() {
		return this.first === this.last
	}
	resize(length) {
		let q = new Array(length)
		for (let i = 0; i < length; i++) {
			q[i] = this.queue[(i + this.first) % this.queue.length]
		}
		this.queue = q
		this.first = 0
		this.last = this.size
	}
}
复制代码
终于水完这篇数据结构队列

Github地址: github.com/Harhao

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值