半路算法之二项树与二项堆

本文探讨了二项树的特性及其与二项式的联系,并介绍了如何利用这些树构建二项堆。二项堆是一种高效的数据结构,适用于实现最小优先队列。文章详细解释了二项堆的基本操作及其实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

半路算法之二项树与二项堆

秉承前文。前面提到过针对稀疏图时,以二项堆来作为最小优先队列是更为适宜的。这里记录一下学习二项堆的过程。

二项堆的名字来源于二项树。二项堆是多个二项树连在了一起。
二项树的名字来源于其 Bn 棵树的元素个数为 2n ,且其深度n处恰有 2k 个节点,其性质与二项式非常吻合。此外,它还是一种递归定义的有序树。
重点依照二项式的性质说一下二项树的性质:

首先二项式定理的公式表示为:

(a+b)n=r=0ncrnanrbr

嗯,在二项树中我们将上式的a和b统统定位1。
那么二项树的第一个性质—— 共有 2k 个节点,便可以理解为上面二项式的值了;
我们假设 树的高度为r(即画出来的树有r行),在 其深度n处有 Ckn 个节点,其中i=0, 1, 2, …, k,理解为其二项式系数,嗯,刚好等于 Ckn
我们假设 根节点(这一行只有它自己,它没有兄弟姐妹节点)的度数为r,它 的度数是这棵二项树上最大的,而且其子女节点分别是它们(子女节点)相对应的子树的根(真有点拗口)

这些性质的证明基本就是二项式定理的证明(数学归纳法,亦即递归)了。这里不再展开。
依据性质1和3,我们知道如果一棵二项树的总结点数为n,那么其节点的最大度数为lgn。

接下来看二项堆。二项堆就是一些二项树把根节点连了起来。它和下一次要讨论的斐波那契堆称为可合并堆,它们支持以下五种操作:

make-heap()     --创建并返回一个不包含任何元素的新堆
insert(H, x)        --将节点x(有值)插入到堆H中
minimum(H)      --返回一个指向堆H中包含最小关键字的节点的指针
extract-min(H)  --将堆H中包含最小关键字的节点删除并返回指向该节点的指针
union(H1, H2)       --创建并返回一个包含堆H1和H2中所有节点的新堆,同时删除堆H1和H2

二项堆中的每个二项树遵循最小堆的性质,其节点的关键字(即节点的值)大于或等于其父节点的关键字。由于二项堆是有二项树拼起来的,其性质完全就是二项树的那些,不再进一步讨论了。

这里重点说说二项堆的函数实现:

新建一个二项堆
嗯,就是分配并返回了一个对象H,且head[H]=NULL,运行时间为O(1)

寻找最小关键字

伪代码
binomial-heap-minimum(H)

y <- NULL
x <- head[H]
min <- ∞
while x≠NULL
    do if key[x]<min
        then min <- key[x]
            y <- x

        x <- sibling[x]
return y

我们需要注意的是关键字只在二项树内排序
代码实现为:

while (x != NULL)
{
    if (x.key < min)
    {
        min = x.key;
        y = x;
        x = x.sibling;
    }
}
return y;

合并两个二项堆

伪代码
binomial-link(y, z)

p[y] <- z
sibling[y] <- child[z]
child[z] <- y
degree[z] <- degree[z]+1

代码实现为:

y.parent = z.child;
z.child = y;
z.degree++;

后面还有合并、插入、取得最小值、去掉最小值、删除某个值的操作。下一篇再写。
另:本篇公式采用MathJax引擎进行了latex公式编写,脚本为:

顺便推荐一下一篇很好的带有常用写法的latex介绍:
一份不太简短的 LATEX 2ε 介绍
星期六, 15. 四月 2017 10:37下午

### 基于51单片机的半路抢答器设计 #### 设计概述 基于51单片机的半路抢答器是一种常见的电子竞赛设备,用于管理多个参赛者之间的快速响应比赛。该系统的核心是8051系列微控制器,其主要职责在于监控输入信号并处理优先级逻辑,最终通过输出接口展示获胜者的编号。 #### 主要组件说明 - **核心控制单元**: 使用AT89C51或其他兼容型号作为中央处理器。 - **按键模块**: 提供四个独立通道给选手操作;每个键对应一路抢答线路。 - **显示装置**: 利用7段LED显示器来指示最先触发成功的那条路径号码。 - **复位开关**: 用来初始化整个系统的状态以便重新开始一轮新的游戏过程[^2]。 #### 软硬件交互原理 每当有任意一位玩家按下自己的按钮时,在对应的I/O端口上会产生一个低电平脉冲变化被CPU捕捉到之后立即锁存起来不再理会后续到来的竞争请求直到下一次重置为止。此同时,软件算法会迅速判断出最早发生的事件并将相应的数值传递给外部驱动电路点亮指定位置上的发光二极管完成视觉反馈效果[^1]。 #### 程序流程图源码实现 下面给出一段简化版的汇编语言程序片段,它实现了基本的功能需求: ```assembly ORG 0H ; 定义起始地址为0 LJMP START ; 长跳转至START处执行代码 ; 初始化子程序 START: MOV P0, #0FFH ; 设置P0口全部为高阻态(准备接收按键输入) SETB IT0 ; 开启INT0中断允许标志位 CLR EA ; 关闭全局中断使能 MAIN_LOOP: SJMP MAIN_LOOP ; 循环等待中断发生 ; 中断服务例程(ISR),假设由第一个按键触发 ORG 03H ; INT0向量表所在的位置 ISR_INT0: PUSH ACC ; 保护现场数据寄存器ACC的内容 SETB TR0 ; 启动定时/计数器T0工作模式 LCALL DISPLAY ; 显示当前选中的队伍号 POP ACC ; 恢复之前保存的数据 RETI ; 返回主函数继续往下走 DISPLAY: ... ; 此处省略具体细节,涉及如何编码以及刷新显示屏的过程 END ; 结束标记 ``` 上述例子仅展示了最基础的部分——即当任一键被按下的瞬间所采取的动作序列。实际应用当中还需要考虑更多因素比如防抖动措施、多轮次支持等功能扩展点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值