JS 数据结构,队列(Queue)

JS数据结构与算法 —— 队列(Queue)


  • 什么是队列 ?

队列(Queue):它是一种 受限的线性表先进先出(FIFO)。受限之处在于,它只能在表的 前端 进行 删除 操作,在表的 后端 进行 插入 操作。

  • 队列的应用 ?
  1. 打印队列:有五份文档需要打印,这些文档会按照次序放入到打印队列中,打印会依次从队列中取出文档,优先放入的文档,优先被取出,并且对该文档进行打印,以此类推,直到队列中不再有新的文档。
  2. 线程队列:在开发中,为了让任务可以并行处理,通常会开启多个线程。但是,我们不能让大量的线程同时运行处理任务,占用资源太多。这个时候,如果有需要开启线程处理的情况,我们就会使用线程队列。线程队列会依次启动线程,并且处理对应任务。(当考虑到线程任务的优先性的时候,可以使用优先队列去完成
  • 队列的实现 ?

队列的实现:可以 基于数组 实现,也可以 基于链表实现(效率更高)。下面先讨论以数组实现的方式,基于链表实现的,后面补充。

// 封装队列类
	function Queue(){
	    // 队列中的属性
		this.items = [];
		// 队列中的操作
		// 1,向队列后端添加元素
		Queue.prototype.enqueue = function(el){
			this.items.push(el);
		}
		// 2,删除队列前端元素,并返回
		Queue.prototype.dequeue = function(){
			return this.items.shift();
		}
		// 3,返回队列前端元素
		Queue.prototype.fork = 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 resultStr = '';
			for(var i=0; i<this.items.length; i++){
				resultStr += this.items[i] + ' ';
			}
			return resultStr;
		}
				
	}
			
	// 使用队列
	var q = new Queue();
	q.enqueue(12);
	q.enqueue(34);
	q.enqueue(14);
	q.enqueue(45);
	alert(q);
	alert(q.dequeue());
	alert(q.fork());
	alert(q.isEmpty());
	alert(q.size());
	alert(q.toString());
  • 面试题——击鼓传花 ?

面试题,击鼓传花:有几个朋友围成一圈玩一个游戏。确定一个数字,当某个人喊到该数字的时候,就出局。直到最后剩下的那个人,则为胜利者,问这个胜利者原本的位置在什么地方?(即原来的下标值)

	// 队列类的封装
	function Queue(){
		// 属性
		this.items = [];
		// 方法
		// 1,队列后端插入元素
		Queue.prototype.enqueue = function(el){
			this.items.push(el);
		}
		// 2,队列前端删除元素,并返回删除的元素
		Queue.prototype.dequeue = function(){
			return this.items.shift();
		}
		// 3,返回队列前端元素,队列不做任何变化
		Queue.prototype.fork = 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 resultStr = '';
			for(var i=0; i<this.items.length; i++){
				resultStr += this.items[i] + ' ';
			}
			return resultStr;
		}
	}
			
	// 击鼓传花的函数,有两个参数,nameList是参加游戏的人的姓名;num是确定的游戏数字
	function transmit(nameList,num){
		// 1,把人全部添加到队列中
		// 1.1,新建队列
		var q = new Queue();
		// 1.2,循环加入队列
		for(var i=0; i<nameList.length; i++){
			q.enqueue(nameList[i]);
		}
		// 2,把队列前num-1个元素移除重新添加到队列后端。把队列?num个元素进行队列前端的删除。依次循环,循环跳出条件为,剩下一个人的时候,即队列长度为一的时候。
		while(q.size > 1){
			// 2.1,将前num-1个元素移动到队列后端
			for(var i=0; i<num-1; i++){
				q.enqueue(q.dequeue());
			}
			// 2.2,删除第num个元素
			q.dequeue();
		}
		// 3,队列中剩下一个元素,即为胜利者
		return nameList.indexOf(q.fork());
}
			
	// 游戏函数测试
	var nameList = ['wuhao','liming','zhousan','yuer','tianwei','sunney'];
	alert(transmit(nameList,3));
  • 优先级队列 ?

优先级队列:优先级队列,属性不仅有元素内容,也包含元素优先级。可以通过元素优先级,将元素放到正确的位置上。

  • 优先级队列的实现 ?

优先级队列的实现 :首先优先级队列属于队列,所以也是可以用数组或者链表去实现它,这里讨论数组的实现思路。优先级队列,和普通队列相比,由于拥有优先级,在队列后端插入元素的时候,要额外的去对比优先级高低,判断合适位置插入。通过可以分为以下三种情况。第一种,队列中没有元素,即首次插入,不用考虑优先级,直接插入即可。第二种,队列非空,插入元素,找到第一个比插入元素优先级大的元素,插入到找出的元素之前即可。第三种,队列非空,遍历后没有比插入元素优先级大的,就插入到队列末尾即可。

// 优先级队列类的封装
	function PriorityQueue(){
		// 在PriorityQueue中重新创建一个类,可以看作内部类
		function QueueItem(element,priority){
			this.element = element;
			this.priority = priority;
		}
		// 封装属性
		this.items = [];
		// 方法
		// 1,队列后端插入元素
		PriorityQueue.prototype.enqueue = function(element,priority){
            // 使用 QueueItem 内部类
			var queueItem = new QueueItem(element,priority);
            // 队列为空,直接添加元素
			if(this.items.length === 0){
				this.items.push(queueItem);
			}else{
				var added = false;
                // 队列不为空,找到大于它优先级的元素,插入到它之前
				for(var i=0; i<this.items.length; i++){
					if(queueItem.priority < this.items[i].priority){
						this.items.splice(i,0,queueItem);
						added = true;
						break;
					}
				}
                // 队列不为空,没有找到大于它优先级的元素,插入到队尾
				if(!added){
					this.items.push(queueItem);
				}
			}
		}
		// 2,队列前端删除元素
		PriorityQueue.prototype.dequeue = function(){
			return this.items.shift();
		}
		// 3,返回队列前端元素,不改变队列
		PriorityQueue.prototype.fork = 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 resultStr = '';
			for(var i=0; i<this.items.length; i++){
				resultStr += this.items[i].element +' :' + this.items[i].priority +' ';
			}
			return resultStr;
		}
	}
			
	// 优先级队列使用
	var pq = new PriorityQueue();
	pq.enqueue('wuhao',110);
	pq.enqueue('liming',10);
	pq.enqueue('zhouyu',80);
	pq.enqueue('huwen',200);
	alert(pq.toString());

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值