11
This commit is contained in:
215
api/middleware/schedule/infrastructure/PriorityQueue.js
Normal file
215
api/middleware/schedule/infrastructure/PriorityQueue.js
Normal file
@@ -0,0 +1,215 @@
|
||||
/**
|
||||
* 优先级队列实现(使用最小堆)
|
||||
* 优先级高的任务(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;
|
||||
|
||||
Reference in New Issue
Block a user