Files
autoAiWorkSys/api/middleware/schedule/PriorityQueue.js
张成 5d7444cd65 1
2025-11-24 13:23:42 +08:00

216 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 优先级队列实现(使用最小堆)
* 优先级高的任务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;