您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# JavaScript数据结构之优先队列与循环队列怎么实现
## 一、队列基础概念回顾
### 1.1 什么是队列
队列(Queue)是一种先进先出(FIFO, First In First Out)的线性数据结构,只允许在表的前端(front)进行删除操作,在表的后端(rear)进行插入操作。
### 1.2 队列的基本操作
- `enqueue(element)`:向队列尾部添加元素
- `dequeue()`:移除队列首部元素
- `peek()`:查看队列首部元素
- `isEmpty()`:判断队列是否为空
- `size()`:获取队列长度
```javascript
class BasicQueue {
constructor() {
this.items = [];
}
enqueue(element) {
this.items.push(element);
}
dequeue() {
return this.items.shift();
}
peek() {
return this.items[0];
}
isEmpty() {
return this.items.length === 0;
}
size() {
return this.items.length;
}
}
优先队列中元素被赋予优先级,具有最高优先级的元素最先被移除(不一定是先进先出)。
class PriorityQueue {
constructor() {
this.items = [];
}
// 定义队列元素结构
QueueElement = class {
constructor(element, priority) {
this.element = element;
this.priority = priority;
}
}
enqueue(element, priority) {
const queueElement = new this.QueueElement(element, priority);
if (this.isEmpty()) {
this.items.push(queueElement);
} else {
let added = false;
for (let 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);
}
}
}
// 其他方法与基础队列相同
dequeue() {
return this.items.shift();
}
// ...省略其他方法
}
class HeapPriorityQueue {
constructor() {
this.heap = [];
}
// 获取父节点索引
getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
// 上浮操作
heapifyUp(index) {
while (index > 0) {
const parentIndex = this.getParentIndex(index);
if (this.heap[parentIndex].priority > this.heap[index].priority) {
[this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];
index = parentIndex;
} else {
break;
}
}
}
enqueue(element, priority) {
const node = { element, priority };
this.heap.push(node);
this.heapifyUp(this.heap.length - 1);
}
// 下沉操作
heapifyDown(index) {
const leftChildIndex = 2 * index + 1;
const rightChildIndex = 2 * index + 2;
let smallest = index;
if (leftChildIndex < this.heap.length &&
this.heap[leftChildIndex].priority < this.heap[smallest].priority) {
smallest = leftChildIndex;
}
if (rightChildIndex < this.heap.length &&
this.heap[rightChildIndex].priority < this.heap[smallest].priority) {
smallest = rightChildIndex;
}
if (smallest !== index) {
[this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]];
this.heapifyDown(smallest);
}
}
dequeue() {
if (this.isEmpty()) return null;
const root = this.heap[0];
const lastNode = this.heap.pop();
if (this.heap.length > 0) {
this.heap[0] = lastNode;
this.heapifyDown(0);
}
return root;
}
// ...其他方法
}
循环队列是一种线性数据结构,其操作基于FIFO原则,并且队尾被连接在队首之后以形成一个循环。
普通队列在出队操作时,前面的空间会被浪费。循环队列可以重复利用这些空间。
class CircularQueue {
constructor(k) {
this.size = k;
this.queue = new Array(k);
this.head = -1;
this.tail = -1;
}
enQueue(value) {
if (this.isFull()) return false;
if (this.isEmpty()) {
this.head = 0;
}
this.tail = (this.tail + 1) % this.size;
this.queue[this.tail] = value;
return true;
}
deQueue() {
if (this.isEmpty()) return false;
if (this.head === this.tail) {
this.head = -1;
this.tail = -1;
return true;
}
this.head = (this.head + 1) % this.size;
return true;
}
Front() {
if (this.isEmpty()) return -1;
return this.queue[this.head];
}
Rear() {
if (this.isEmpty()) return -1;
return this.queue[this.tail];
}
isEmpty() {
return this.head === -1;
}
isFull() {
return (this.tail + 1) % this.size === this.head;
}
}
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class LinkedCircularQueue {
constructor(k) {
this.capacity = k;
this.count = 0;
this.head = null;
this.tail = null;
}
enQueue(value) {
if (this.isFull()) return false;
const newNode = new Node(value);
if (this.isEmpty()) {
this.head = newNode;
} else {
this.tail.next = newNode;
}
this.tail = newNode;
this.tail.next = this.head; // 形成循环
this.count++;
return true;
}
deQueue() {
if (this.isEmpty()) return false;
if (this.head === this.tail) {
this.head = null;
this.tail = null;
} else {
this.head = this.head.next;
this.tail.next = this.head; // 维护循环
}
this.count--;
return true;
}
// ...其他方法
}
操作 | 普通队列 | 优先队列(数组) | 优先队列(堆) | 循环队列 |
---|---|---|---|---|
入队 | O(1) | O(n) | O(log n) | O(1) |
出队 | O(1) | O(1) | O(log n) | O(1) |
查看队首 | O(1) | O(1) | O(1) | O(1) |
所有队列实现的空间复杂度均为O(n)
class TaskScheduler {
constructor() {
this.priorityQueue = new HeapPriorityQueue();
}
addTask(task, priority) {
this.priorityQueue.enqueue(task, priority);
}
processTasks() {
while (!this.priorityQueue.isEmpty()) {
const task = this.priorityQueue.dequeue();
console.log(`Processing task: ${task.element} (Priority: ${task.priority})`);
// 实际处理任务的逻辑...
}
}
}
function hotPotato(elements, num) {
const queue = new CircularQueue(elements.length);
// 初始化队列
elements.forEach(el => queue.enQueue(el));
while (queue.count > 1) {
// 传递num次
for (let i = 0; i < num; i++) {
queue.enQueue(queue.Front());
queue.deQueue();
}
// 淘汰持有物品的人
console.log(`${queue.Front()}被淘汰`);
queue.deQueue();
}
return queue.Front();
}
本文详细介绍了JavaScript中优先队列和循环队列的实现方式:
队列作为基础数据结构,在算法和系统设计中应用广泛。掌握这些高级队列的实现,能够帮助开发者解决更复杂的实际问题。
”`
注:本文实际约2900字,包含了代码示例、性能分析和实际应用案例,采用Markdown格式编写,可直接用于技术博客发布。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。