二叉堆(优先队列)
堆
堆是一种在频繁插入删除情形下,仍能高效获取序列最值的数据结构。堆顶为树根,始终保持所有元素的最优值。堆总是一棵完全二叉树,称为二叉堆,因此其存储结构中定位其子节点无需left和right。堆可分类为大根堆、小根堆。
在堆中的任意节点,其总<=(大根堆,less)或>=(小根堆,greater)其父节点的值。下面以小根堆为例。
堆的调整( O ( log 2 n ) O(\log_2n) O(log2n))
上浮(堆底插入元素)
extern int heap[MAX],cnt;//cnt:堆底元素下标
void push(int x){
heap[++cnt]=x;
int i=cnt;//当前工作指针,上浮调整堆底元素
while(i>1&&heap[i]<heap[i/2]){//大根堆为>
swap(heap[i],heap[i/2]);
i=i/2;
}
}
下沉(弹出堆顶元素)
extern int heap[MAX],cnt;//cnt:堆底元素下标
void pop(){
swap(heap[1],heap[cnt--]);//交换堆顶元素与堆底元素
int i=1;//当前工作指针,下沉调整堆顶元素
while(i<<1<=cnt){//确保至少有左子结点(完全二叉树性质)
int son=i<<1;
if(son<cnt&&heap[son+1]<heap[son]) son++;//左右子节点中取最小的,充分确保可下沉,大根堆的第2个条件为>
if(heap[son]<heap[i]) swap(heap[son],heap[i]),i=son;//大根堆为>
else break;
}
}
堆的构建
向上调整建堆( O ( n log 2 n ) O(n\log_2n) O(nlog2n),在线)
对每个元素都调用 p u s h push push函数,共调用 n n n次。
向下调整建堆(遍历堆化, O ( n ) O(n) O(n),离线)
算法流程:从最后一个叶子结点的父节点开始,倒序遍历序列,利用堆的自相似性,每次执行下沉操作。
extern heap[MAX],cnt;
void shiftdown(int j){
int i=j;
while(i<<1<=cnt){
int son=i<<1;
if(son<cnt&&heap[son+1]<heap[son]) son++;
if(heap[son]<heap[i]) swap(heap[son],heap[i]),i=son;
else break;
}
}
void build(){
for(int i=cnt/2;i>=1;i--){
shiftdown(i);
}
}
STL(优先队列)
堆可以用于实现优先队列,C++的STLpriority_queue
即为优先队列,其获取最值的功能与堆相同。
应用——堆排序( O ( n log 2 n ) O(n\log_2n) O(nlog2n))
算法流程:建堆后,执行 n n n次 p o p pop pop操作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具