具体堆的知识可进入该网站浏览:
https://blog.csdn.net/qq_34270874/article/details/113091364
#include <iostream> #include <vector> using namespace std; class MaxHeap { public: void push(int x) { heap.push_back(x); siftUp(heap.size() - 1); } int top() { if (heap.empty()) return -1; return heap[0]; } int pop() { if (heap.empty()) return -1; int maxVal = heap[0]; heap[0] = heap.back(); heap.pop_back(); siftDown(0); return maxVal; } private: vector<int> heap; void siftUp(int idx) { int parent = (idx - 1) / 2; while (idx > 0 && heap[idx] > heap[parent]) { swap(heap[idx], heap[parent]); idx = parent; parent = (idx - 1) / 2; } } void siftDown(int idx) { int size = heap.size(); while (true) { int leftChild = 2 * idx + 1; int rightChild = 2 * idx + 2; int maxIdx = idx; if (leftChild < size && heap[leftChild] > heap[maxIdx]) maxIdx = leftChild; if (rightChild < size && heap[rightChild] > heap[maxIdx]) maxIdx = rightChild; if (maxIdx == idx) break; swap(heap[idx], heap[maxIdx]); idx = maxIdx; } } }; int main() { int n; cin >> n; MaxHeap heap; for (int i = 0; i < n; i++) { string op; cin >> op; if (op == "push") { int x; cin >> x; heap.push(x); } else if (op == "top") { int result = heap.top(); if (result == -1) cout << "empty" << endl; else cout << result << endl; } else if (op == "pop") { int result = heap.pop(); if (result == -1) cout << "empty" << endl; else cout << result << endl; } } return 0; }
siftUp(heap.size() -1)
是在将新素插入堆后,调用siftUp函数将新元素向上移动到合适的位置,以维持大根的性质。
siftUp
函数的作用是比较当前与其父节点的大小关系,如果当前节点的值大于其父节点值,则交换它们的位置,直到当前节点不再比父节点大或者到达堆顶。
siftUp
函数的实现中,传入的参数idx
为当前在堆中的索引。首先计算当前节点的父节点的索引位置parent = (idx - 1) / 2
,然后进行循环比较交换操作,直到当前节点不再比父节点大或者到达堆顶为止。
具体的比较交换操作如下:
- 如果当前节点的值大于其父节点的值,交换当前节点和父节点的值,将当前节点的索引更新为父节点的索引
idx = parent
。 - 继续计算新的当前节点的父节点索引
parent = (idx - 1) / 2
,并进行下一轮的比较交换操作。
通过这一系列的比较和交换操作,新插入的元素会被逐渐向上移动到合适的位置,从而满足大根堆的性质。
在siftUp
函数执行完毕后,新元素已经被正确插入并移动到了合适的位置,保持了大根堆的性质。
int maxVal = heap[0];
heap[0] = heap.back();
heap.pop_back();
siftDown(0);
的作用是实现移除堆顶元素,并将堆中最后一个元素放到堆顶位置,然后调用siftDown(0)
函数将新的堆顶元素下移到合适的位置,以维持大根堆的性质。
首先,定义一个整数变量maxVal
,将堆顶元素的值heap[0]
赋给它,即取出堆顶元素的值。
然后,将堆中最后一个元素的值heap.back()
赋给堆顶元素heap[0]
,即将堆顶元素替换为最后一个元素。
接着,调用pop_back()
函数将堆中的最后一个元素删除。
最后,调用siftDown(0)
函数,将新的堆顶元素下移到合适的位置,以维持大根堆的性质。
siftDown
函数的作用是比较当前节点与其左右子节点的大小关系,如果当前节点的值小于左子节点或右子节点的值,则将当前节点与较大的子节点交换位置,直到当前节点不再比两个子节点小或者到达堆底部。
siftDown
函数的实现中,传入的参数idx
为当前在堆中的索引。首先计算当前节点的左右子节点的索引位置left = 2 * idx + 1
和right = 2 * idx + 2
,然后进行循环比较交换操作,直到当前节点不再比两个子节点小或者到达堆底部为止。
具体的比较交换操作如下:
- 如果当前节点的值小于左子节点的值,交换当前节点和左子节点的值,将当前节点的索引更新为左子节点的索引
idx = left
。 - 如果当前节点的值小于右子节点的值,交换当前节点和右子节点的值,将当前节点的索引更新为右子节点的索引
idx = right
。 - 继续计算新的当前节点的左右子节点索引
left = 2 * idx + 1
和right = 2 * idx + 2
,并进行下一轮的比较交换操作。
通过这一系列的比较和交换操作,新的堆顶元素会被逐渐向下移动到合适的位置,从而满足大根堆的性质。
在siftDown
函数执行完毕后,新的堆顶元素已经被正确移动到了合适的位置,保持了大根堆的性质。
如果以上解析有帮助到你,麻烦给个吧,如果有任何问题也可指出一起交流解决。