二叉堆
讲述最小堆的实现。
实现push功能
void put(int x)
{
arr[++cnt]=x; //将数据存在数组的最后面
int son=cnt;
while(arr[son/2]>arr[son]) swap(arr[son/2],arr[son]),son=son/2;//将整个二叉堆变得正确,从子节点一直向上推,类似于线段树的更新实现
}
实现pop功能
int get()
{
int fa=1,ans=arr[1],son,flag=1; //先把堆顶的元素取出来
arr[1]=arr[cnt--]; //把堆的最后一个元素放到堆顶
while((fa*2<=cnt||fa*2+1<=cnt)&&flag) //如果没有越界
{
if(fa*2+1>cnt||arr[fa*2]<arr[fa*2+1]) son=fa*2; //找到左右儿子节点较小的那一边
else son=fa*2+1;
if(arr[fa]>arr[son]) swap(arr[fa],arr[son]),fa=son; //互换父亲节点和较小子节点的值
else flag=0; //否则此二叉堆已经是合法二叉堆,就可以结束循环
}
return ans;
}
完整的代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e+5;
int arr[maxn],cnt;
void put(int x)
{
arr[++cnt]=x;
int son=cnt;
while(arr[son/2]>arr[son]) swap(arr[son/2],arr[son]),son=son/2;
}
int get()
{
int fa=1,ans=arr[1],son,flag=1;
arr[1]=arr[cnt--];
while((fa*2<=cnt||fa*2+1<=cnt)&&flag)
{
if(fa*2+1>cnt||arr[fa*2]<arr[fa*2+1]) son=fa*2;
else son=fa*2+1;
if(arr[fa]>arr[son]) swap(arr[fa],arr[son]),fa=son;
else flag=0;
}
return ans;
}
int main()
{
freopen("in.txt","r",stdin);
int n;
for(int i=0; i<10; i++) cin>>n,put(n);
for(int i=0; i<10; i++) printf("%d ",get());
return 0;
}
/*
输入
10 9 5 4 8 3 2 6 1 7
输出
1 2 3 4 5 6 7 8 9 10
*/