zoukankan      html  css  js  c++  java
  • 二叉树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;
    }
  • 相关阅读:
    堆排序
    冒泡排序
    描述字符串写入文件
    Java Socket编程,读服务器几个字符,再写入本地显示。
    final,finally,finalize区别
    圆桌问题 (a)
    表达式
    计算系数
    乌龟棋
    显示图像(多源dfs)
  • 原文地址:https://www.cnblogs.com/oleolema/p/9028437.html
Copyright © 2011-2022 走看看