堆排序
传送门
#include <iostream>
#include <algorithm>
using namespace std;
const int N =1000010;
int h[N];
int n,m,size;
void down(int i){
int u=i;
if(2*u<size&&h[2*u]<h[t])t=2*u;
if(2*u+1<size&&h[2*u+1]<h[t])t=2*u+1;
if(u!=t){
swap(h[t],h[u]);
down(t);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>h[i];
size=n;
for(int i=n/2;i;i--)down(i);
while(m--){
cout<<h[1];
h[1]=h[size];
size--;
down(1);
}
}
用数组存储堆,
如上都是来自https://www.acwing.com/大佬的解题模板
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
const int N =1e6+10;
int heap[N],size;
using namespace std;
int top(){
return heap[1];
}
void push(int x){
heap[++size]=x;
int temp=size;
while(temp>1){
int next=temp>>1;
if(heap[next]<=heap[temp])
return ;
swap(heap[next],heap[temp]);
temp=next;
}
}
void pop(){
heap[1]=heap[size--];
int temp=1;
while(temp<<1<=size){
int next=temp<<1;
if(heap[next]>heap[next+1])
next++;
if(heap[temp]<=heap[next])
return ;
swap(heap[temp],heap[next]);
temp=next;
}
}
int main(){
int n;
cin>>n;
for(int opt,x;n;n--){
cin>>opt;
switch(opt){
case 1:{
cin>>x;
push(x);
break;
}
case 2:{
cout<<top()<<endl;
break;
}
case 3:{
pop();
}
}
}
return 0;
}
堆(heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
-
堆中某个结点的值总是不大于或不小于其父结点的值;
-
堆总是一棵完全二叉树。
push操作
那么多的节点我们要插入到那里,不管插到那里我们还需要移动本来位置上的节点,所以我们索性直接插到树的最后面去,我们最需跟它的父节(tmep>>1)点作比较,若是小根堆的话,保证头节点最小就可以了
heap[++size]=x;
int temp=size;
while(temp>1){
int next=temp>>1;
if(heap[next]<=heap[temp])
return ;
swap(heap[next],heap[temp]);
temp=next;
}
pop操作
大佬们太绝了,我刚拿到这个还纠结把heap[1]去掉了,这个树如何重建尼,大佬们直接将堆的最后一个拉上来heap([1]=heap[size--]),然后让heap[1]往下走所有的顾虑就迎刃而解了
heap[1]=heap[size--];
int temp=1;
while(temp<<1<=size){
int next=temp<<1;
if(heap[next]>heap[next+1])
next++;
if(heap[temp]<=heap[next])
return ;
swap(heap[temp],heap[next]);
temp=next;
}