自定义模板化Priority Queue的Push/Pop函数异常排查求助
嘿,我帮你找到了问题的根源——两个关键错误组合在一起,导致你的优先级队列输出完全不符合预期。咱们一步步拆解:
第一个致命错误:Top函数完全写反了
你的top()函数返回的是数组最后一个元素value[siz-1],但最大堆的堆顶元素应该是数组的第一个元素value[0]啊!这直接导致你打印的根本不是优先级最高的元素,而是队列里的最后一个元素。
修正后的Top函数应该是这样:
V top() const { // 最好加个非空判断,避免空队列访问出错,比如: // if (empty()) throw std::runtime_error("Priority queue is empty"); return value[0]; }
第二个核心错误:Pop函数逻辑完全偏离堆的实现规则
你的Pop函数做了完全相反的操作,正确的最大堆Pop流程应该是:
- 取出堆顶元素(要返回的优先级最高值)
- 把队列最后一个元素移到堆顶位置
- 缩小队列大小
- 将这个新堆顶元素下沉到合适的位置(和左右子节点比较,交换到符合堆性质的位置)
但你的代码先从堆顶开始用子节点覆盖父节点,这会直接丢失元素、破坏堆结构,后续的操作自然全错了。
下面是修复后的Pop函数:
template <class V> V MyPriorityQueue<V>::pop() { // 先保存堆顶元素,最后返回 V val = value[0]; // 把最后一个元素移到堆顶,替代被取出的元素 value[0] = value[siz - 1]; // 队列大小减一 siz--; // 开始下沉操作:把堆顶元素放到正确位置 int index = 0; while (true) { int left_child = 2 * index + 1; int right_child = 2 * index + 2; int largest_node = index; // 记录当前最大的节点索引 // 比较左子节点和当前节点,更新最大节点 if (left_child < siz && value[left_child] > value[largest_node]) { largest_node = left_child; } // 比较右子节点和当前最大节点,更新最大节点 if (right_child < siz && value[right_child] > value[largest_node]) { largest_node = right_child; } // 如果当前节点已经是最大的,说明下沉完成,退出循环 if (largest_node == index) { break; } // 交换当前节点和最大子节点 swap(value[index], value[largest_node]); // 继续向下处理 index = largest_node; } return val; }
验证修复效果
把Top和Pop函数都修正后,用你原来的测试代码运行:
MyPriorityQueue<int> pq; pq.push(14); pq.push(6); pq.push(3); pq.push(19); pq.push(9); while(!pq.empty()) { cout << pq.top() << endl; pq.pop(); }
就能得到预期的输出:19 → 14 → 9 → 6 → 3。
另外提一句,你的Push函数逻辑是对的,扩容和上浮操作都没问题,不用修改~
内容的提问来源于stack exchange,提问作者Haider Bokhari
相关产品推荐
相关产品推荐

