【数据结构三】队列

队列:

队列结构:Queue,也是一种常见的数据结构。它是一种受限的线性结构,在队尾插入元素,在队首删除元素,先进先出(FIFO,first in first out)。

生活中的队列:

比如:在银行排队办理业务,后到的人只能排在队伍的末端,开始营业时队伍前端的人先办理业务。

程序中的队列:

比如:JS 是单线程的,在执行代码时会有多个任务,这些任务会在线程中排队按顺序依次执行。

队列的实现:

本章基于数组来实现队列结构。

// 封装队列
function Queue() {
	// 队列中的元素
	this.items = []
}
// 队列中的操作
// 向队列尾部添加一个新的项
Queue.prototype.enqueue = function(element) {
	this.items.push(element)
}
// 移除队首的第一个项,并返回被移除的元素
Queue.prototype.dequeue = function() {
	this.items.shift()
}
// 返回队首的第一个元素,队列不做任何变动
Queue.prototype.front = function() {
	return this.items[0]
}
// 如果队列中没有任何元素就返回 true,否则返回 false
Queue.prototype.isEmpty = function() {
	return this.items.length === 0
}
// 返回队列中的元素个数
Queue.prototype.size = function() {
	return this.items.length
}
// 将队列结构的内容以字符串形式返回
Queue.prototype.toString = function() {
	return this.items.join(' ')
}
// 调用队列
var q = new Queue()
q.enqueue(10)
q.enqueue(20)
console.log(q.toString())

队列的应用:

将击鼓传花的游戏规则改一下:几个朋友一起玩一个游戏,围成一圈开始数数,数到某个数字的人自动淘汰,由他后面的人再次重新开始数数,一直到最后剩下的人获得胜利,问最后剩下的人在原来的哪一个位置?

// 击鼓传花游戏
function passGame(nameList, num) {
  // 创建一个队列结构
  var queue = new Queue()
  
  // 将所有人依次加入到队列中
  for(var i = 0; i < nameList.length; i++) {
    queue.enqueue(nameList[i])
  }

  // 开始数数字:只要队列中剩余的人数大于1就一直循环数数
  while(queue.size() > 1) {
    // num 数字之前的人,从原队列中删除并重新加入到队列的末尾
    for(var i = 0; i < num - 1; i++) {
      var name = queue.dequeue()
      queue.enqueue(name)
    }
    // 是 num 这个数字的人,将其从队列中删除
    queue.dequeue()
  }
  
  // 返回最终剩下的那个人
  return queue.front()
}

console.log(passGame(['Tom', 'Mary', 'Lee', 'Lucy', 'Lily'], 3)) // Lucy

优先级队列:

在普通的队列中插入一个元素,元素会被放在队尾,并且需要前面所有的元素都处理完后才会处理该元素。

而优先级队列,在插入一个元素的时候就会考虑该元素的优先级,会将该元素与其他元素的优先级进行比较,从而得出这个元素在队列中的正确的位置。

生活中的优先级队:

比如:机场登机的顺序,头等舱和商务舱乘客登机的优先级要高于经济舱乘客。

程序中的优先级队列:

比如:每个线程处理的任务的重要性不同,就可以通过优先级的大小,来决定该线程在队列中被处理的顺序。

优先级队列的实现:

在实现优先级队列时,需要考虑两个问题:每个元素不再只是一个数据,而且还需要包含数据的优先级;在添加元素的时候,需要将元素的优先级和队列中已经存在的元素的优先级进行比较,将其放入正确的位置。

// 封装节点类
function Node(element, priority) {
  // 优先级队列中的节点需要包含两个内容:一个是元素本身的数据,另一个是优先级
  this.element = element
  this.priority = priority
}
// 封装优先级队列:值越小,越排列在前面
function PriorityQueue() {
	// 队列中的元素
	this.items = []
}
// 队列中的操作
// 向队列中添加一个新的项
PriorityQueue.prototype.enqueue = function(element, priority) {
  // 1. 创建节点
  var node = new Node(element, priority)

	// 2. 判断队列是否为空,为空的话将元素直接添加进去
  if (this.isEmpty()) {
    this.items.push(node)
    return false
  }

  // 3. 不为空则进行比较
  var addred = false
  for(var i = 0; i < this.size(); i++) {
    // 是按优先级从小到大排列的,因此判断到当前元素的优先级比某个元素小,插入到这个元素前面
    if (priority < this.items[i].priority) {
      this.items.splice(i, 0, node)
      addred = true
      break
    }
  }

  // 4. 如果当前元素的优先级比队列中任何一个元素的都大,则插入到队尾
  if (!addred) {
    this.items.push(node)
  }
}
// 移除队首的第一个项,并返回被移除的元素
PriorityQueue.prototype.dequeue = function() {
	return this.items.shift()
}
// 返回队首的第一个元素,队列不做任何变动
PriorityQueue.prototype.front = function() {
	return this.items[0]
}
// 如果队列中没有任何元素就返回 true,否则返回 false
PriorityQueue.prototype.isEmpty = function() {
	return this.items.length === 0
}
// 返回队列中的元素个数
PriorityQueue.prototype.size = function() {
	return this.items.length
}
// 将队列结构的内容以字符串形式返回
PriorityQueue.prototype.toString = function() {
    var resultStr = ''
    for(var i = 0; i < this.size(); i ++) {
      resultStr += `${this.items[i].element}-${this.items[i].priority} `
    }
    return resultStr
}
// 调用优先级队列
var pq = new PriorityQueue()
pq.enqueue('Mary', 40)
pq.enqueue('Lily', 10)
pq.enqueue('Tom', 20)
pq.enqueue('Bob', 30)
console.log(pq.toString()) // Lily-10 Tom-20 Bob-30 Mary-40 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值