优先队列:
优先队列的实现是大顶堆(优先级最高的元素再前面),对于节点数量为n的大顶堆,插入元素与弹出元素的时间复杂读为O(log(n)),询问的时间复杂度为O(1)。
首先我们需要将数组映射到完全二叉树上。
对于数组[16, 7, 3, 20, 17, 8]映射为:
从后到前调整非叶子节点与子节点的位置:
对于大小为n的二叉树,需要调整的第一个节点为n/2号节点。
为了方便理解我们以16(7,3)表示父亲节点为16,子节点从左到右以此为7,3。
步骤1:调整原始完全二叉树。
1.3(8),子节点8比3大调整为8(3)。
2.7(20,17),子节点20比7大调整为20(7,17)
3.16(20,8),调整为20(16,8)
4.16(7,17),调整为17(7,16)
最后得到:
步骤二:当我们需要查看最大元素时,我们只需要返回Tree[1],(节点1即可,也就是根节点)
步骤三:当我们需要插入最大元素时,Tree[++n] = new Node Value,然后通过步骤1类似调整,得到所需完全二叉树。
步骤四:删除最大元素时,我们仅需要将树的大小缩小为n-1,将节点n与1进行交换,后对树进行更新.
C++实现:
#include <iostream>
#include <cstring>
using namespace std;
#define N 100005
int heap[N];
int n,u;
int size = 0;
void swap(int &x,int &y){
int t=x;
x=y;
y=t;
return ;
}
void Up_update(int t){
while(t>1){
if(heap[t]>heap[t/2]){
swap(heap[t],heap[t/2]);
t/=2;
}
else return ;
}
return ;
}
void Down_update(int p){
while(p<=size){
int son=p*2;
if(son<n&&heap[son]<heap[son+1])son++;
if(heap[p]<heap[son]){
swap(heap[p],heap[son]);
p=son;
}
else return ;
}return ;
}
int Get_Max(){
return heap[1];
}
int main(){
cin>>n;
/**
当我们需要将数组中n个整数插入堆时,我们只需要插入到最后,然后向上更新。
**/
for(int i=0;i<n;i++){
cin>>u;
heap[++size] = u;
Up_update(size);
}
cout<<Get_Max()<<endl;
/**
* 当我们需要添加元素时我们仅需要将添加元素向上更新;
* **/
cin>>u;
heap[++size] = u;
Up_update(size);
/**
* 当我们需要删除优先级最大元素时,我们需要将heap[size]与heap[1]进行交换,数组大小缩小为size - 1
* 向下更新
* */
swap(heap[1],heap[size]);
size --;
Down_update(1);
/**
* 当我们需要得到最大元素时,我们只需要输出heap[0]。
* */
cout<<Get_Max()<<endl;
}