二叉树练习题(21.8.3)

Trees on the level:建二叉树+广搜
题意: 告诉你一些字符串,如(12,LL)表示12在根结点的左儿子的左儿子的结点处,()表示一组字符串输入结束。输出完全指定的二叉树的顺序遍历。如果没有完全指定一棵树,(即树中的某个节点没有被赋予一个值,或者一个节点不止一次地被赋予一个值),输出“NotComplete”。
思路: 先把题目中的字符串中的整数和字母分开,建树的时候按照字母顺序找到相应结点,然后插入整数。在插数的同时要判断一下是否已经插过了。然后通过广搜按照顺序输出即可。
补充:
substr()
截取字符串:s.substr(pos, len),s必须是字符串,如果是char型数组要先转换。pos表示在第几位(包括0),len表示截取长度(len如果省去,表示从pos位截取到末尾)
strchr()函数
函数原型为:char * strchr(char * str, char/int c);
表示在字符串str中寻找字符C第一次出现的位置,并返回其位置(地址指针),若失败则返回NULL;
atoi()函数
函数原型:int atoi(const char *str);
把参数 str 所指向的字符串转换为一个int型整数

#include<bits/stdc++.h>
using namespace std;
const int N=256+5;
bool fail;//bool类型的fail,用于判断,错误赋1,没错赋0
vector<int>ans;
char s[N];
struct Node
{
    
    
    bool is;//是否被赋值
    int value;//结点的值
    Node *l,*r;//左右结点
    Node():is(false),l(NULL),r(NULL) {
    
    }
};
Node * root;//根结点
Node * newNode()//建新结点
{
    
    
    return new Node();
}
void remove_tree(Node * root)//清除二叉树
{
    
    
    if(root==NULL)
        return;
    remove_tree(root->l);
    remove_tree(root->r);
    delete root;
}
void insertNode(int t,char * ss)//插入
{
    
    
    //t表示插入的价值,ss为插入的序列
    int n=strlen(ss);
    Node *p=root;
    for(int i=0; i<n; i++)
    {
    
    
        if(ss[i]=='L')
        {
    
    
            if(p->l==NULL)
                p->l=newNode();
            p=p->l;
        }
        else if(ss[i]=='R')
        {
    
    
            if(p->r==NULL)
                p->r=newNode();
            p=p->r;
        }
    }//以上步骤负责定位到待插入的结点
    if(p->is)//已经赋值过,输入错误
    {
    
    
        fail=true;
    }
    p->value=t;
    p->is=true;
}
//广搜,返回值为是否某一结点未被赋值
bool bfs(vector<int>&ans)//vector作为函数的参数或者返回值时,&不能省
{
    
    
    queue<Node *>q;//广搜需要的队列
    ans.clear();//清除上一次序列
    q.push(root);//根结点入队
    while(!q.empty())
    {
    
    
        Node *p=q.front();//指针指向第一个元素的位置
        q.pop();//剔除第一个元素
        if(!p->is)//结点未被赋值
        {
    
    
            return false;
        }
        ans.push_back(p->value);//将结点的值加到vector的最后面
        if(p->l!=NULL)
        {
    
    
            q.push(p->l);//左子结点入队
        }
        if(p->r!=NULL)
        {
    
    
            q.push(p->r);//右子结点入队
        }
    }
    return true;
}
int main()
{
    
    
    int c=1;
    while(c)
    {
    
    
        remove_tree(root);//清除上一棵二叉树
        fail=false;//初始化
        root=newNode();
        while(1)
        {
    
    
            if(scanf("%s",s)!=1)//如果s被成功读入就返回1,否则返回0
            {
    
    
                c=0;
                break;
            }
            if(!strcmp(s,"()"))//比较字符串s和(),s<()返回-1,s>()返回1,相等返回0
            {
    
    
                break;//如果s==(),停止输入
            }
            string ss,str(s);//s变成字符串str
            ss=str.substr(1);//去掉“(”
            int val=atoi(ss.c_str());//字符串转数字
            insertNode(val,strchr(s,',')+1);//strchr返回首次出现“,”位置的下一位的指针
            //插入结点
        }
        if(c==0)
            continue;
        if(!bfs(ans))//如果某一结点没有被赋值,则错误
        {
    
    
            fail=true;
        }
        if(fail)
        {
    
    
            cout<<"not complete"<<endl;
        }
        else {
    
    
            for(int i=0;i<ans.size();i++)
            {
    
    
                if(i!=0)
                    cout<<" ";
                cout<<ans[i];
            }
            cout<<endl;
        }
    }
    return 0;
}

解题心得:菜鸟忧伤,研究一下午终于仿照人家的代码写出来了,思路上差不多就是老出错,现在还没搞明白啥时候用指针函数和指针参数,暂时先硬记吧,希望做多了能明白套路,先挖个坑。

猜你喜欢

转载自blog.csdn.net/weixin_51443397/article/details/119356672