其实堆就是一个特殊的完全二叉树(当然,所有用堆的题目都可以用线段树解决),堆分最小堆和最大堆,我们这里先介绍最小堆。
定义:
最小堆,是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。
构造:
先一个个输入元素key【i】,将其构造成一个二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。
for(int i=1;i<=n;i++)
{
cin>>key[i];
up(i);
}
然而up是什么呢?详情请见代码
void up(int k)
{
int fa=k/2;
if (fa>0)
{
if (key[fa]>key[k]) //如果父亲节点大于儿子节点就交换
{
swap(key[fa], key[k]);
up(fa);
}
}
}
这么我们的堆就建好了!
大家可以试试下面的程序。
#include<bits/stdc++.h>
using namespace std;
int key[100001],n;
void up(int k)
{
int fa=k/2;
if(fa>0)
{
if(key[fa]>key[k])
{
swap(key[fa],key[k]);
up(fa);
}
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>key[i];
up(i);
}
for(int i=1;i<=n;i++)
{
cout<<key[i]<<" ";
}
return 0;
}
我们接下来就要对堆做删除(弹出)操作了。
献上一道练习题。
pop操作很简单,push更是简单,我就直接上代码了:
#include<bits/stdc++.h>
using namespace std;
int key[100001],n,q=0;
void up(int k)
{
int fa = k / 2;
if (fa > 0)
{
if (key[fa] < key[k])
{
swap(key[fa], key[k]);
up(fa);
}
}
}
void down(int k)
{
int son = k * 2;
if (son <= q)
{
if (son + 1 <= q)
if (key[son] < key[son+1])
son = son + 1;
if (key[son] > key[k])
{
swap(key[son], key[k]);
down(son);
}
}
}
int main()
{
cin>>n;
for(int i = 1; i <= n; i++)
{
string w;
cin>>w;
if(w=="push")
{
cin >> key[++q];
up(q);//维护这个堆
}
else
{
if(q==0)
{
cout<<"empty"<<endl;
}
else
{
cout << key[1] << endl;//输出栈顶元素(即最小值)
key[1] = key[q--];//将最后一个数提到最前面,q--,然后再维护这个堆,实现了pop操作
down(1);
}
}
}
return 0;
}
谢谢大家!