#include<cstdio>
#include<algorithm>
// for test
#include<queue>
using namespace std;
// 学习堆的代码
// 建立堆
// 堆使用数组表示
const int maxn = 100;
// 0 不存储元素,1开始存储元素
// i * 2 为左孩子, i * 2 + 1 为右孩子
int heap[maxn] = {0};
int n = 0; // n为元素个数
// 下调整代码,以堆顶一个元素为中心,往下调整
// 需要保证中心元素的左右子树的根节点都是子树中的最大值
// 用于堆排序和取堆顶元素,建立堆时也可以使用
void down_adjust(int low, int high){
int i = low, j = i * 2; // i为父亲节点,j暂时指向其左孩子
while(j <= high){ // 存在孩子节点
// 如果左右节点都有的话,j指向左右节点中最大的
if(j + 1 <= high && heap[j] < heap[j + 1]){
j = j + 1;
}
// 向下调整开始
if(heap[i] < heap[j]){
swap(heap[i], heap[j]);
i = j;
j = i * 2;
} else{
break; // 不需要调整了就在这里跳出循环,孩子的权值均比父亲小了
}
}
}
// 建堆
void create_heap(){
// 二叉树1~下取整(2/n)的节点都是非叶子节点,从每个非叶子节点倒着来
for(int i = n / 2; i >= 1; i--){// 反着来是-- 千万别++
down_adjust(i, n); // 这里是从小到大调,顺序不能错
}
}
// 删堆顶
void delete_top(){
heap[1] = heap[n--];// 最后一个元素覆盖堆顶元素
down_adjust(1, n);// 以堆顶元素为中心,向下调整至叶子
}
// 向上调整操作
// 一般用于堆元素的添加
void up_adjust(int low, int high){
int i = high, j = i / 2; // i为预调整节点,j是i的父亲节点
while(j >= low){
if(heap[j] < heap[i]){
swap(heap[j], heap[i]);
i = j; // 保持i为欲调整节点
j = i / 2; // j 为 i 的父亲节点
} else{
break; // 无需调整则结束
}
}
}
// 向堆中插入元素的函数
void insert_node(int x){
heap[++n] = x;
up_adjust(1, n);
}
int main(){
// 建堆的测试代码
// 1. 建堆之后看看对不对
printf("Create heap test:\n");
int a[10] = {85, 55, 82, 57, 68, 92, 99, 98, 66, 56};
for(int i = 0; i < 10; i++){
heap[i + 1] = a[i];
n ++;
}
create_heap();
//层次遍历堆
int i = 1;
queue<int> q;
// 读第一个节点
printf("%d ", heap[i]);
// 把第一个节点放进队列
q.push(i);
while(!q.empty()){
if(q.front() * 2 <= n){
i = q.front() * 2;
printf("%d ", heap[i]);
q.push(i);
}
if(q.front() * 2 + 1 <= n){
i = q.front() * 2 + 1;
printf("%d ", heap[i]);
q.push(i);
}
q.pop();
}
printf("\n");
// 2. 插入测试
printf("Insert heap top test:\n");
insert_node(107);
//层次遍历堆
i = 1;
// 读第一个节点
printf("%d ", heap[i]);
// 把第一个节点放进队列
q.push(i);
while(!q.empty()){
if(q.front() * 2 <= n){
i = q.front() * 2;
printf("%d ", heap[i]);
q.push(i);
}
if(q.front() * 2 + 1 <= n){
i = q.front() * 2 + 1;
printf("%d ", heap[i]);
q.push(i);
}
q.pop();
}
printf("\n");
// 3. 删堆肯定是从大到小删堆
printf("Delete heap top test:\n");
while(n != 0){
printf("%d ", heap[1]);
delete_top();
}
printf("\n");
return 0;
}
【机试练习】【C++】堆练习
最新推荐文章于 2024-04-22 12:48:38 发布