堆的构造和应用

1.如何构造堆(以小根堆为例)

①以完全二叉树的方式从左往右将新元素插入到最后的位置;
②从下往上更新,与父结点比较,若小于父结点,则与父结点交换位置,若大于则更新完成。
如:10,9,8,7,6构造小根堆
在这里插入图片描述

2.如何进行堆排序

①将堆顶元素与最后一个未固定的元素交换;
②从上往下,若父结点小于左右子结点则更新完成,否则找出左右子结点中小于父结点的更小的那一个,与父结点交换位置;
③循环①②,每轮确定一个数的位置,直到所有节点被固定。
在这里插入图片描述

3.如何找出2000万个数中前1000个最大的数

①使用前1000个数构造小根堆;
②遍历后续的数,若小于堆顶元素则跳过,若大于则替换堆顶元素并更新堆;
  更新的流程为:从上往下,若父结点小于左右子结点则更新完成,否则找出左右子结点中小于父结点的更小的那一个,与父结点交换位置。

以下是C++代码实现: ```c++ #include <iostream> #include <vector> using namespace std; // 构造最大 void buildMaxHeap(vector<int>& nums) { int n = nums.size(); for (int i = n / 2 - 1; i >= 0; i--) { // 从最后一个非叶子节点开始向下调整 int parent = i; int leftChild = parent * 2 + 1; while (leftChild < n) { int rightChild = parent * 2 + 2; int maxChild = leftChild; if (rightChild < n && nums[rightChild] > nums[leftChild]) { maxChild = rightChild; } if (nums[maxChild] > nums[parent]) { swap(nums[parent], nums[maxChild]); parent = maxChild; leftChild = parent * 2 + 1; } else { break; } } } } // 排序 void heapSort(vector<int>& nums) { int n = nums.size(); for (int i = n - 1; i >= 1; i--) { swap(nums[0], nums[i]); // 将当前最大值放到末尾 int parent = 0; int leftChild = parent * 2 + 1; while (leftChild < i) { // 从根节点开始向下调整 int rightChild = parent * 2 + 2; int maxChild = leftChild; if (rightChild < i && nums[rightChild] > nums[leftChild]) { maxChild = rightChild; } if (nums[maxChild] > nums[parent]) { swap(nums[parent], nums[maxChild]); parent = maxChild; leftChild = parent * 2 + 1; } else { break; } } } } int main() { int n; cin >> n; vector<int> nums(n); for (int i = 0; i < n; i++) { cin >> nums[i]; } // 排序前 for (int i = 0; i < n; i++) { cout << nums[i]; if (i < n - 1) { cout << " "; } } cout << endl; // 构造最大 buildMaxHeap(nums); // 构造后 for (int i = 0; i < n; i++) { cout << nums[i]; if (i < n - 1) { cout << " "; } } cout << endl; // 排序后 heapSort(nums); for (int i = 0; i < n; i++) { cout << nums[i]; if (i < n - 1) { cout << ","; } } cout << endl; return 0; } ``` 输入示例: ``` 8 3 1 4 1 5 9 2 6 ``` 输出示例: ``` 3 1 4 1 5 9 2 6 9 5 4 6 1 3 2 1 1,1,2,3,4,5,6,9 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值