算法入门经典第六章数据结构—树和二叉树-1.二叉树的编号

本文介绍了一种计算小球在二叉树中下落路径的高效算法。通过分析小球下落规律,利用小球编号的奇偶性判断其在树中的走向,避免使用大数组模拟,实现简洁快速求解。

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

问题描述:一棵二叉树的深度为D。所有结点从上到下从左到右编号依次为1,2,3,…,2^D-1,在结点1处放一个小球。每个结点有个开关,初始全部关闭,当每次球落到一个结点上,此结点的开关状态放上改变。球如果遇到关闭的结点向左走,否则向右。输入小球个数I,输出第I个小球最后落到的叶子编号。

                1
           2          3
        4    5     6     7
       8 9 10 11 12 13 14 15

我们如果用一个数组s来保存这个树中结点的状态,刚开始这个数组全部赋为0表示全部结点的开关为关闭状态。比如上图是一个深度D为4的二叉树,如果输入I为2,模拟一下下落过程。
1.第一个小球从1开始,因为刚开始所有结点的开关都关闭,所以一直向左,顺序为1->2->4->8,而小球落到一个结点开关状态改变,所以1,2,4,8都改变为开启状态(即s[1、2、4、8]都为1)。
2.第二个小球从1开始,因为1状态为开启,所以向右到达3,而从以3开始的子树的状态还依然是关闭,所以从3开始都向左走,所以第二个小球的下落顺序为1->3->6->12
3.输出12
这个过程还是很容易理解的,并且用数组来解决也是很自然的,但是当D很小时候这个没什么大运算量,但是当D很大时候,因为I可达2^D-1,所以这个数组要开的特别特别大,很显然,根本不现实。
所以,有了另外一个神奇的方法。

我们分析一下,每个小球刚开始都是从根结点1开始的,第一个小球向左,第二个向右,第三个向左,第四个….,所以就直接用I的奇偶性来判断小球落在那棵子树上。对于那些落入根结点左子树的小球来说,只需要知道该小球是第几个落在根的左子树里,就能知道向左还是向右了,如果是第一个落在根的左子树里,就是向左,第二个就向右(注意这个第二不是第二个小球,而是第二个落在左子树
当I为奇数时,则它是往左走的第(I+1)/2个小球;如果是偶数,则是往右走的第I/2个小球。
所以,减少了数组,直接模拟第I个小球的下落路线

#include<cstdio>
using namespace std;

int main()
{
    int D,I;
    while(scanf("%d%d",&D,&I)==2)
    {
        int k=1; 
        for(int i=0;i<D-1;i++)
        if(I%2) 
        {
            I = (I+1)/2;
            k=k*2;
        }
        else{
            I = I/2;
            k=k*2+1;
        } 
        printf("%d\n",k);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值