数据结构——队列
数据结构特点
队列是遵循先进先出(FIFO,也称为先来先服务)。队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。
常见场景
队列方法
- enqueue(element(s)):向队列尾部添加一个(或多个)新的项
- dequeue():移除队列的第一项(即排在队列最前面的项)并返回被移除的元素
- peek():返回队列中第一个元素——最先被添加,也将是最先被移除的元素。队列不做任何变动(不移除元素,只返回元素信息——与Stack类的peek方法非常类似)。该方法在其他语言中也可以叫作front方法。
- isEmpty():如果队列中不包含任何元素,返回true,否则返回false。
- size():返回队列包含的元素个数,与数组的length属性类似
队列实现
// 队列,先进先出
class Queue {
constructor() {
// 记录队列尾的索引
this.count = 0
//用对象存放队列值
this.items = {}
//记录队列首的索引
this.lowestCount = 0
}
// 队尾添加元素
enqueue(ele) {
this.items[this.count] = ele
this.count++
}
dequeue() {
if (this.isEmpty()) {
return undefined
}
const res = this.items[this.lowestCount]
delete this.items[this.lowestCount]
this.lowestCount++
return res
}
isEmpty() {
return this.size() === 0
}
size(){
return this.count - this.lowestCount
}
peek(){
if(this.isEmpty()) return undefined
return this.items[this.lowestCount]
}
clear(){
this.items = {}
this.count = 0
this.lowestCount = 0
}
toString(){
if(this.isEmpty()) return ''
let objString = this.items[this.lowestCount]
for(let i = this.lowestCount+1;i<this.count;i++){
objString = `${objString},${this.items[i]}`
}
return objString
}
}
let queue = new Queue()
console.log(queue.enqueue('a'))
console.log(queue.enqueue('b'))
console.log(queue.enqueue('c'))
console.log(queue.toString())
console.log(queue.dequeue())
console.log(queue.size())
console.log(queue.isEmpty())
console.log(queue.peek())
console.log(queue.clear())
console.log(queue.isEmpty())
//输出结果
undefined
undefined
undefined
a,b,c
a
2
false
b
undefined
true
数据结构——双端队列
数据结构特点
允许我们同时从前端和后端添加和移除元素的特殊队列。是结合了队列和栈的双重特点的队列。
常见场景
常见方法
- addFront(element):该方法在双端队列前端添加新的元素。
- addBack(element):该方法在双端队列后端添加新的元素(实现方法和Queue类中的enqueue方法相同)。
- removeFront():该方法会从双端队列前端移除第一个元素(实现方法和Queue类中的dequeue方法相同)。
- removeFront():该方法会从双端队列前端移除第一个元素(实现方法和Queue类中的dequeue方法相同)。
- peekFront():该方法返回双端队列前端的第一个元素(实现方法和Queue类中的peek方法一样)。
- peekBack():该方法返回双端队列后端的第一个元素(实现方法和Stack类中的peek方法一样)。
其他还包括isEmpty、clear、size、toString方法。
队列实现
// 双端队列,队手和队尾都可以增加删除
class Deque {
constructor() {
// 记录队列尾的索引
this.count = 0
//用对象存放队列值
this.items = {}
//记录队列首的索引
this.lowestCount = 0
}
// 队尾添加元素,count永远指向下一个,注意peek的时候也需要注意count-1
addBack(ele) {
this.items[this.count] = ele
this.count++
}
addFront(ele) {
if (this.isEmpty()) {
this.addBack(ele)
} else if (this.lowestCount > 0) {
this.lowestCount--
this.items[this.lowestCount] = ele
} else {
for (let i = this.lowestCount; i < this.count; i++) {
this.items[i + 1] = this.items[i]
}
this.count++
this.items[this.lowestCount] = ele
}
}
removeFront() {
if (this.isEmpty()) {
return undefined
}
const res = this.items[this.lowestCount]
delete this.items[this.lowestCount]
this.lowestCount++
return res
}
removeBack() {
if (this.isEmpty()) return undefined
const res = this.items[this.count]
delete this.items[this.count]
this.count--
return res
}
isEmpty() {
return this.size() === 0
}
size() {
return this.count - this.lowestCount
}
peekFront() {
if (this.isEmpty()) return undefined
return this.items[this.lowestCount]
}
//需要注意count是下一个
peekBack() {
if (this.isEmpty()) return undefined
return this.items[this.count - 1]
}
clear() {
this.items = {}
this.count = 0
this.lowestCount = 0
}
toString() {
if (this.isEmpty()) return ""
let objString = this.items[this.lowestCount]
for (let i = this.lowestCount + 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`
}
return objString
}
}
const deque = new Deque()
console.log(deque.addFront("a"))
console.log(deque.peekFront())
console.log(deque.peekBack())
deque.addBack('b')
console.log(deque.toString())
console.log(deque.size())
//输出结果
undefined
a
a
a,b
2
常见面试题
1.击鼓传花
游戏规则: 在这个游戏中,孩子们围成一个圆圈,把花尽快地传递给旁边的人。某一时刻传花停止,这个时候花在谁手里, 谁就退出圆圈、结束游戏。重复这个过程,直到只剩一个孩子(胜者) eleList:参与击鼓传花的名单 num 代表传递的次数 输出被删除的人和剩余的队列
function hotPhtato(eleList, num) {
while (eleList.length > 1) {
for (let i = 0; i < num; i++) {
eleList.push(eleList.shift())
}
console.log(`${eleList.shift()}被淘汰`)
}
console.log(`${eleList.shift()}胜出`)
}
hotPhtato(["John", "Jack", "Camila", "Carl", "Ingrid"], 4)
输出结果
Ingrid被淘汰
John被淘汰
Camila被淘汰
Carl被淘汰
Jack胜出
|