zoukankan      html  css  js  c++  java
  • Trees on the level UVA

    题目链接:https://vjudge.net/problem/UVA-122

    题目大意:输入一颗二叉树,你的任务是按从上到下,从左到右的顺序输出各个结点的值。每个结点都按照从根节点到它的移动序列给出(L表示左,R表示右) 在输入中,每个结点的左括号

    和右括号之间没有空格,相邻结点之间用一个空格隔开。每棵树的输入用一对空括号)()结束  入上图所示:

    注意:如果从根结点到某个叶节点的路径有的结点没有在输入中给出,或者给出超过一次,输出not complete。  结点个数不超过256

    思路:显然是二叉树的层次遍历。

    首先看一下输入部分:

    bool read_input()//读入字符
    {
        failed=false;//记录是否输入有误
        remove_tree(root);//释放内存空间
        root=newnode();//创建根节点
        for(;;)
        {
            if(scanf("%s",s)!=1) return false;//整个输入结束
            if(!strcmp(s,"()")) break;//读到结束标志 退出循环
            int v;
            sscanf(&s[1],"%d",&v);//读入节点值
            addnode(v,strchr(s,',')+1);//
        }
        return true;
    }

    这里要学一下sscanf的用法  strchr的用法

    接下来看一下建树的代码:

    void addnode(int v,char* s)
    {
        int len=strlen(s);
        Node* u=root;//从根节点往下走
        for(int i=0;i<len;i++)//找到当前位置
        {
            if(s[i]=='L')
            {
                if(u->Left==NULL) u->Left=newnode();//节点不存在 建立新节点
                u=u->Left;
            }
            else if(s[i]=='R')
            {
                if(u->Right==NULL) u->Right=newnode();
                u=u->Right;
            }
            //忽略其他情况   即最后多余的那个空格
    
        }
        if(u->have_value) failed=true;//已经赋过值 表明输入有误
        u->v=v;//没有误 给节点赋值 
        u->have_value=true;//标记已经赋值
    }

     建完树之后便是层次遍历的过程了,这里用bfs来写:

    bool bfs(vector<int>& ans)
    {
        queue<Node*> q;
        ans.clear();
        q.push(root);//初始时只有一个根节点
        while(!q.empty())
        {
            Node* u=q.front();
            q.pop();
            if(!u->have_value) return false;//有节点没有被赋值过 表明输入有误
            ans.push_back(u->v);//增加到输出序列尾部
            if(u->Left!=NULL) q.push(u->Left);
            if(u->Right!=NULL) q.push(u->Right);
        }
        return true;
    }

    这里有一块代码 是释放内存的  没有也不会错

    void remove_tree(Node* u)
    {
        if(u==NULL) return ;
        remove_tree(u->Left);//递归释放左子树的空间
        remove_tree(u->Right);//
        delete u;
    }

    下面看完整代码:

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<vector>
    #include<queue>
    using namespace std;
    const int maxn=256+5;
    char s[maxn];//保存读入的节点
    bool failed;
    struct Node{
        bool have_value;//是否被赋值过
        int v;//结点值
        Node *Left,*Right;
        Node()
        {
            have_value=false;
            Left=NULL;
            Right=NULL;
        }
    };
    Node *root;
    void remove_tree(Node* u)
    {
        if(u==NULL) return ;
        remove_tree(u->Left);//递归释放左子树的空间
        remove_tree(u->Right);//
        delete u;
    }
    Node* newnode()
    {
        return new Node();
    }
    void addnode(int v,char* s)
    {
        int len=strlen(s);
        Node* u=root;//从根节点往下走
        for(int i=0;i<len;i++)//找到当前位置
        {
            if(s[i]=='L')
            {
                if(u->Left==NULL) u->Left=newnode();//节点不存在 建立新节点
                u=u->Left;
            }
            else if(s[i]=='R')
            {
                if(u->Right==NULL) u->Right=newnode();
                u=u->Right;
            }
            //忽略其他情况   即最后多余的那个空格
    
        }
        if(u->have_value) failed=true;//已经赋过值 表明输入有误
        u->v=v;//没有误 给节点赋值 
        u->have_value=true;//标记已经赋值
    }
    bool read_input()//读入字符
    {
        failed=false;//记录是否输入有误
        remove_tree(root);//释放内存空间
        root=newnode();//创建根节点
        for(;;)
        {
            if(scanf("%s",s)!=1) return false;//整个输入结束
            if(!strcmp(s,"()")) break;//读到结束标志 退出循环
            int v;
            sscanf(&s[1],"%d",&v);//读入节点值
            addnode(v,strchr(s,',')+1);//
        }
        return true;
    }
    /*
        这样一来 输入和建树部分就已经结束了  接下来只需要按照层次顺序遍历这棵树
        此处使用一个队列来完成这个任务  初始时只有一个根节点  然后每次取出一个节点
        就把它的左右子结点放入队列中
    */
    bool bfs(vector<int>& ans)
    {
        queue<Node*> q;
        ans.clear();
        q.push(root);//初始时只有一个根节点
        while(!q.empty())
        {
            Node* u=q.front();
            q.pop();
            if(!u->have_value) return false;//有节点没有被赋值过 表明输入有误
            ans.push_back(u->v);//增加到输出序列尾部
            if(u->Left!=NULL) q.push(u->Left);
            if(u->Right!=NULL) q.push(u->Right);
        }
        return true;
    }
    
    int main()
    {
    
        while(read_input())
        {
            vector<int>ans;
            vector<int>::iterator it;
            if(failed||(!bfs(ans))) printf("not complete
    ");
            else
            {
                it=ans.begin();
                printf("%d",*it);
                it++;
                for(it;it!=ans.end();it++)
                printf(" %d",*it);
                printf("
    ");
            }
    
        }
    
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    Android之Wifi使用
    Android之浮动小窗口
    Android之Socket的基于UDP传输
    Android之基本常见知识(持续更新)
    Android之打开闪光灯关键代码
    Android之Oauth验证(一)
    Android之WebView简易应用
    Android之短信广播接收内容
    Google HTML/CSS 代码风格指南
    几个 HTML 标签的用法
  • 原文地址:https://www.cnblogs.com/caijiaming/p/10350119.html
Copyright © 2011-2022 走看看