216 lines
5.1 KiB
JavaScript
216 lines
5.1 KiB
JavaScript
/**
|
||
* 优先级队列实现(使用最小堆)
|
||
* 优先级高的任务(priority值大)会优先出队
|
||
*/
|
||
class PriorityQueue {
|
||
constructor() {
|
||
this.heap = [];
|
||
}
|
||
|
||
/**
|
||
* 获取父节点索引
|
||
*/
|
||
parent(index) {
|
||
return Math.floor((index - 1) / 2);
|
||
}
|
||
|
||
/**
|
||
* 获取左子节点索引
|
||
*/
|
||
leftChild(index) {
|
||
return 2 * index + 1;
|
||
}
|
||
|
||
/**
|
||
* 获取右子节点索引
|
||
*/
|
||
rightChild(index) {
|
||
return 2 * index + 2;
|
||
}
|
||
|
||
/**
|
||
* 交换两个节点
|
||
*/
|
||
swap(i, j) {
|
||
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
|
||
}
|
||
|
||
/**
|
||
* 上浮操作(插入时使用)
|
||
*/
|
||
bubbleUp(index) {
|
||
if (index === 0) return;
|
||
|
||
const parentIndex = this.parent(index);
|
||
const current = this.heap[index];
|
||
const parent = this.heap[parentIndex];
|
||
|
||
// 优先级高的在前(priority值大),如果优先级相同,创建时间早的在前
|
||
if (
|
||
current.priority > parent.priority ||
|
||
(current.priority === parent.priority && current.createdAt < parent.createdAt)
|
||
) {
|
||
this.swap(index, parentIndex);
|
||
this.bubbleUp(parentIndex);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 下沉操作(删除时使用)
|
||
*/
|
||
bubbleDown(index) {
|
||
const leftIndex = this.leftChild(index);
|
||
const rightIndex = this.rightChild(index);
|
||
let largest = index;
|
||
|
||
const current = this.heap[index];
|
||
|
||
// 比较左子节点
|
||
if (leftIndex < this.heap.length) {
|
||
const left = this.heap[leftIndex];
|
||
if (
|
||
left.priority > current.priority ||
|
||
(left.priority === current.priority && left.createdAt < current.createdAt)
|
||
) {
|
||
largest = leftIndex;
|
||
}
|
||
}
|
||
|
||
// 比较右子节点
|
||
if (rightIndex < this.heap.length) {
|
||
const right = this.heap[rightIndex];
|
||
const largestNode = this.heap[largest];
|
||
if (
|
||
right.priority > largestNode.priority ||
|
||
(right.priority === largestNode.priority && right.createdAt < largestNode.createdAt)
|
||
) {
|
||
largest = rightIndex;
|
||
}
|
||
}
|
||
|
||
if (largest !== index) {
|
||
this.swap(index, largest);
|
||
this.bubbleDown(largest);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 添加任务到队列
|
||
* @param {Object} task - 任务对象,必须包含 priority 和 createdAt 属性
|
||
*/
|
||
push(task) {
|
||
if (!task.hasOwnProperty('priority')) {
|
||
task.priority = 5; // 默认优先级
|
||
}
|
||
if (!task.hasOwnProperty('createdAt')) {
|
||
task.createdAt = Date.now();
|
||
}
|
||
this.heap.push(task);
|
||
this.bubbleUp(this.heap.length - 1);
|
||
}
|
||
|
||
/**
|
||
* 取出优先级最高的任务
|
||
* @returns {Object|null} 任务对象或null
|
||
*/
|
||
pop() {
|
||
if (this.heap.length === 0) {
|
||
return null;
|
||
}
|
||
|
||
if (this.heap.length === 1) {
|
||
return this.heap.pop();
|
||
}
|
||
|
||
const top = this.heap[0];
|
||
this.heap[0] = this.heap.pop();
|
||
this.bubbleDown(0);
|
||
|
||
return top;
|
||
}
|
||
|
||
/**
|
||
* 查看优先级最高的任务(不移除)
|
||
* @returns {Object|null} 任务对象或null
|
||
*/
|
||
peek() {
|
||
return this.heap.length > 0 ? this.heap[0] : null;
|
||
}
|
||
|
||
/**
|
||
* 获取队列大小
|
||
* @returns {number}
|
||
*/
|
||
size() {
|
||
return this.heap.length;
|
||
}
|
||
|
||
/**
|
||
* 检查队列是否为空
|
||
* @returns {boolean}
|
||
*/
|
||
isEmpty() {
|
||
return this.heap.length === 0;
|
||
}
|
||
|
||
/**
|
||
* 清空队列
|
||
*/
|
||
clear() {
|
||
this.heap = [];
|
||
}
|
||
|
||
/**
|
||
* 查找任务
|
||
* @param {Function} predicate - 查找条件函数
|
||
* @returns {Object|null} 任务对象或null
|
||
*/
|
||
find(predicate) {
|
||
return this.heap.find(predicate) || null;
|
||
}
|
||
|
||
/**
|
||
* 移除任务
|
||
* @param {Function} predicate - 查找条件函数
|
||
* @returns {boolean} 是否成功移除
|
||
*/
|
||
remove(predicate) {
|
||
const index = this.heap.findIndex(predicate);
|
||
if (index === -1) {
|
||
return false;
|
||
}
|
||
|
||
if (index === this.heap.length - 1) {
|
||
this.heap.pop();
|
||
return true;
|
||
}
|
||
|
||
// 将最后一个元素移到当前位置
|
||
this.heap[index] = this.heap.pop();
|
||
|
||
// 重新调整堆
|
||
const parentIndex = this.parent(index);
|
||
if (index > 0 && this.heap[parentIndex] &&
|
||
(this.heap[index].priority > this.heap[parentIndex].priority ||
|
||
(this.heap[index].priority === this.heap[parentIndex].priority &&
|
||
this.heap[index].createdAt < this.heap[parentIndex].createdAt))) {
|
||
this.bubbleUp(index);
|
||
} else {
|
||
this.bubbleDown(index);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 转换为数组(用于调试)
|
||
* @returns {Array}
|
||
*/
|
||
toArray() {
|
||
return [...this.heap];
|
||
}
|
||
}
|
||
|
||
module.exports = PriorityQueue;
|
||
|