堆(优先队列)

堆是一种在频繁插入删除情形下,仍能高效获取序列最值的数据结构。堆顶为树根,始终保持所有元素的最优值。堆总是一棵完全二叉树,称为二叉堆,因此其存储结构中定位其子节点无需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操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值