题目如下:
描述
定义一个数组,初始化为空。在数组上执行两种操作:
1、增添1个元素,把1个新的元素放入数组。
2、输出并删除数组中最小的数。
使用堆结构实现上述功能的高效算法。
对于每组测试数据,第一行输入一个整数n,代表操作的次数。
每次操作首先输入一个整数type。
当type=1,增添操作,接着输入一个整数u,代表要插入的元素。
当type=2,输出删除操作,输出并删除数组中最小的元素。
1<=n<=100000。
2 5 1 1 1 2 1 3 2 2 4 1 5 1 1 1 7 2
1 2 1
需要使用最小堆结构来实现本题的算法
以前写树的代码时一直用的链表形式,现在试了一下数组的写法,感觉比较也比较好理解,写法也比较简单。代码及注释如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[100010];
int n;
//下标下移,在删除后更新树时需要用到
void down( int root )
{
int son = 2*root; //记录根节点的左儿子
int t = a[root];
while( son <= n)
{
if( son <= n -1 && a[son] > a[son+1]) //防止数组越界,且记录较小值儿子节点的下标
son++;
if( t > a[son]) //更新节点。
{
a[root] = a[son];
root = son;
son = 2*root;
}
else break;
}
a[root] = t;
}
//数组下标上移,插入节点时用到。
void up( int son )
{
int t = a[son];
int tson = son;
while( (tson > 1)&&( a[tson/2] > t)) //更新节点。
{
a[tson] = a[tson/2];
tson = tson/2;
}
a[tson] = t;
}
void charu( int t)
{
a[ ++n ] = t;
up( n );
}
void del( )
{
if(n==0)
return ;
cout << a[1] << endl; //根节点肯定是最小值。
a[1] = a[n--];
down( 1 );
}
int main()
{
int t;
scanf("%d",&t);
while( t-- )
{
n = 0;
int type;
int m;
scanf("%d",&m);
for(int i = 0; i< m; i++)
{
scanf("%d",&type);
if(type == 1)
{
int b;
scanf("%d",&b);
charu( b ) ;
}
else
{
del();
}
}
}
return 0;
}