关于建堆和调整为堆的思想,可以看这篇文章
void createHeap(vector<int> &nums);
void heapAdjust(vector<int> &nums, int rootIdx, int m);
void insertHeap(vector<int> &nums, int val);
int deleteHeap(vector<int> &nums);
// 根结点从 1 开始,方便右移寻找父节点!!!
int main() {
vector<int> nums = {0, 49, 38, 65, 97, 76, 13, 27, 49};
// 建堆
createHeap(nums);
cout << "top = " << nums[1] << endl; // top = 97
int valInsert = 99;
cout << "valInsert = " << valInsert << endl; // valInsert = 99
insertHeap(nums,valInsert);
cout << "top = " << nums[1] << endl; // top = 99
int val = deleteHeap(nums);
cout << "val of delete = " << val << endl; // val of delete = 99
cout << "top = " << nums[1] << endl; // top = 97
val = deleteHeap(nums);
cout << "val of delete = " << val << endl; // val of delete = 97
cout << "top = " << nums[1] << endl; // top = 76
}
void createHeap(vector<int> &nums){
int len = nums.size();
// 建初堆
for (int i = len / 2; i >= 1; i--){
heapAdjust(nums, i, len - 1);
}
}
void heapAdjust(vector<int> &nums, int rootIdx, int m){
// 函数功能:调整为大根堆
// 将以 rootIdx 为根结点,结束结点的下标是 m 的子树调整为大根堆
int pivot = nums[rootIdx];
int j = 2 * rootIdx; // 左孩子结点
for (j; j <= m; j *= 2){
if (j < m && nums[j] < nums[j + 1]){ // 找出孩子结点中的最大值
j++;
}
if (pivot >= nums[j]){ // 本身就是大根堆
break;
}
nums[rootIdx] = nums[j];
rootIdx = j;
}
nums[rootIdx] = pivot;
}
void insertHeap(vector<int> &nums, int val){
// 函数功能:将元素val插入堆
// 主要思想:将待插入的值放到末尾,然后从 此元素 开始 自底向上调整为大根堆
// 这里不做内存是否溢出的判断
nums.push_back(val);
// 自底向上调整
int j = nums.size() - 1;
for (j; nums[j >> 1] < val; j >>= 1){
// 如果插入的元素大于其父节点,将父节点移到该元素的位置,继续向上比较
nums[j] = nums[j >> 1];
if ((j >> 1) == 0){
break;
}
}
nums[j] = val;
}
int deleteHeap(vector<int> &nums){
// 函数功能:删除堆顶元素,并返回删除的值
// 主要思想:用堆的最后一个叶子结点去填补根结点,然后自顶向下调整为堆
int len = nums.size();
int val = nums[1]; // 需要返回的堆顶元素
nums[1] = nums[len - 1]; // 将最后一个元素放到根结点(堆顶)
nums.pop_back(); // 删除最后一个元素
len--; // 长度减 1
heapAdjust(nums, 1, len - 1); // 将以 根结点 为根的树调整为堆
return val;
}