JavaScript实现PriorityQueue时无法添加多个节点的报错排查
问题根因
错误触发的核心原因是bubbleUp方法的while循环缺失边界校验:当子节点上浮到数组的根节点位置(索引为0)时,继续计算父节点索引会得到Math.floor((0-1)/2) = -1,此时访问values[-1].priority就会抛出「读取undefined属性priority」的错误。
你之前的console.log能够正常打印,是因为第一次进入循环前,父节点索引为0、子节点索引为1(第二个元素的索引),两个节点均存在,所以打印正常。当第二个节点的优先级小于根节点优先级时,会进入循环完成交换,交换后子节点索引变为0,再次计算父节点索引为-1,此时执行while条件判断就会触发错误。
修复方案
在while循环的判断条件中增加父节点索引合法性校验parentIndex >= 0即可解决问题,同时可以优化冗余代码,修复后的完整代码如下:
class PriorityQueue { constructor() { this.values = [] } enqueue(value, priority) { // 可去掉空数组的特殊判断,bubbleUp逻辑对空数组push后的场景也兼容 this.values.push({value, priority}); this.bubbleUp(this.values); return this.values; } bubbleUp(values) { let childIndex = values.length - 1; let parentIndex = Math.floor((childIndex - 1) / 2); // 新增parentIndex >= 0的边界校验 while (parentIndex >= 0 && values[childIndex].priority < values[parentIndex].priority) { // 交换逻辑可以用数组解构简化,无需临时变量 [values[childIndex], values[parentIndex]] = [values[parentIndex], values[childIndex]]; childIndex = parentIndex; parentIndex = Math.floor((childIndex - 1) / 2); } return values; } }
验证方法
你可以用以下测试用例验证修复效果:
const pq = new PriorityQueue(); pq.enqueue('任务1', 2); pq.enqueue('任务2', 1); // 之前触发错误的场景,修复后可正常执行 console.log(pq.values); // 输出符合最小堆规则的优先级队列结构
内容的提问来源于stack exchange,提问作者ShashankAC
相关产品推荐
相关产品推荐

