二叉树1 (猴子下山)

描述

有一颗二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从左到右从上到下的编号为1,2,3,…,2的D次方减1(满二叉树)。在结点1处放一个小猴子,它会往下跑。每个内结点上都有一个开关,初始全部关闭,当每次有小猴子跑到一个开关上时,它的状态都会改变,当到达一个内结点时,如果开关关闭,小猴子往左走,否则往右走,直到走到叶子结点。

一些小猴子从结点1处开始往下跑,最后一个小猴儿会跑到哪里呢?

 输入

输入二叉树叶子的深度D,和小猴子数目I,假设I不超过整棵树的叶子个数,D<=20.最终以 0 0 结尾

输出

输出第I个小猴子所在的叶子编号。

样例输入

4 2

3 4

0 0

样例输出

12

7

题目信息告诉我们得用二叉树解决,所以可以毫不犹豫地创建二叉树。

用链式二叉树:

#include"iostream"
#include"queue"
#include"cmath"
using namespace std;
typedef int element;

static bool *change;            //记录结点开关
static int count1;                //记录猴子到达个数
class Tree{
private:
    element data;
    Tree *right;
    Tree *left;
public:

    Tree(){}
    Tree(element data){
        this->data = data;
        right = NULL;
        left = NULL;
    }
    void createSQTree(Tree* &t,int n){
        queue<Tree*> q;
        int i = 0;
        t = new Tree(++i);
        Tree *p = t;
        q.push(p);
        while(i != n){
            p = q.front();
            p->left = new Tree(++i);
            q.push(p->left);
            if(i == n){
                break;
            }
            p->right = new Tree(++i);
            q.push(p->right);
            q.pop();
        }
    }
    void destroy(){
        if(this){
            left->destroy();
            right->destroy();    
            delete this;
        }
    }
    void showx(Tree* t,int momkey){
        if(t){
            if(t->left == NULL && t->right == NULL && count1 == momkey - 1){
                cout<<t->data<<endl;
                return ;
            }
            if(change[t->data]){
                change[t->data] = false;
                showx(t->left,momkey);
            }
            else{
                change[t->data] =true;
                showx(t->right,momkey);
            }
        }
        else{
            if(++count1 == momkey){
                return ;
            }
            showx(this,momkey);
        }
    }
};

int main(){
    Tree *t = NULL;
    while(true){
        int d;                //深度
        int momkey;            //猴子个数
        cin>>d>>momkey;
        if(d==0&&momkey==0){
            break;
        }
        count1 = 0;
        int num = pow(2,d) - 1;    //结点个数
        change = new bool[num + 1];
        for(int i = 0;i < num;i++){
            change[i] = true;
        }    
        t->createSQTree(t, num);
        t->showx(t,momkey);
        t->destroy();
        delete[] change;
    }
    return 0;
}

但我们发现创建二叉树来模拟每一步骤的效率不高,而且代码量太大,所以可以采用下面这种方法。 

把数组看做二叉树:

//精简版
#include"iostream"
using namespace std;
int main(){
    int tree[1024],i;
    int d, momkey;
    while(cin>>d>>momkey && d && momkey){
        memset(tree,0,sizeof(tree));
        while(momkey--){
            int d1 = d;
            i = 1;
            while(--d1){
                if(tree[i] == 0){
                    tree[i] = 1;
                    i += i;
                }
                else{
                    tree[i] = 0;
                    i += i + 1;
                }
            }
        }
        cout<<i<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/oleolema/p/9028437.html