堆是一种特殊的数据结构,通常用于实现优先队列和排序算法。堆通常被描述为一棵完全二叉树,其中每个节点都比它的子节点大(或者小)。
一般情况下,有两种类型的堆:最大堆和最小堆。在最大堆中,每个节点的值都大于或等于它的子节点的值,而在最小堆中,每个节点的值都小于或等于它的子节点的值。
堆的操作有两种:上浮和下沉,上浮对应优先队列的插入操作push(),下沉对应优先队列的删除队头的操作()。
接下来以洛谷p3378堆为例,实现手写堆和优先队列:
手写堆:
#include<bits/stdc++.h>
#define N 3000000
#define ll long long
using namespace std;
int heap[N],len = 0;
void push(int x) {
heap[++len] = x;
int i = len;
while( i > 1 && heap[i] < heap[i/2]){
swap(heap[i],heap[i/2]);
i = i/2;
}
}
void pop() {
heap[1] = heap[len--];
int i = 1;
while(2*i <= len) {
int lson = 2 * i;
if(lson < len && heap[lson + 1] < heap[lson]) lson++;
if(heap[lson] < heap[i])
{
swap(heap[lson],heap[i]);
i = lson;
}
else break;
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
int op;
scanf("%d",&op);
if(op == 1) {
int x;
scanf("%d",&x);
push(x);
}
else if(op == 2) printf("%d\n",heap[1]);
else pop();
}
}
STL:
#include<bits/stdc++.h>
#define N 3000000
#define ll long long
using namespace std;
priority_queue< int , vector<int> , greater<int> >q;
int main()
{
int n;
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
int op;
scanf("%d",&op);
if(op == 1) {
int x;
scanf("%d",&x);
q.push(x);
}
else if(op == 2) printf("%d\n",q.top());
else q.pop();
}
}