问题 N: 二叉树的创建和文本显示

问题 N: 二叉树的创建和文本显示

题目描述
编一个程序,读入先序遍历字符串,根据此字符串建立一棵二叉树(以指针方式存储)。
例如如下的先序遍历字符串:
A ST C # # D 10 # G # # F # # #
各结点数据(长度不超过3),用空格分开,其中“#”代表空树。
建立起此二叉树以后,再按要求输出二叉树。

输入
输入由多组测试数据组成。

每组数据包含一行字符串,即二叉树的先序遍历,字符串长度大于0且不超过100。

输出
对于每组数据,显示对应的二叉树,然后再输出一空行。输出形式相当于常规树形左旋90度。见样例。 注意二叉树的每一层缩进为4,每一行行尾没有空格符号。

样例输入 Copy
A ST C # # D 10 # G # # F # # #
4 2 1 # # 3 # # 5 # 6 # #
样例输出 Copy
A
            F
        D
                G
            10
    ST
        C

        6
    5
4
        3
    2
        1

实现过程

题目内容:

编写一个程序,该程序能够读取一个表示二叉树先序遍历的字符串,并据此创建一棵二叉树。二叉树的节点存储数据,并且每个节点都有指向左子树和右子树的指针。如果先序遍历字符串中的某个位置是空树,使用特殊字符“#”表示。

例如,给定以下先序遍历字符串:

A ST C # # D 10 # G # # F # #

该字符串表示的二叉树应该被如下创建:

  • 根节点是“A”,其左子树是“ST”,右子树是“C”。
  • “ST”的左右子树都不存在(用“#”表示)。
  • “C”的左子树是“D”,右子树是“10”。
  • “D”和“10”的左右子树都不存在。
  • “C”的右子树是“G”,但它的左右子树不存在。
  • “A”的右子树是“F”,但它的左右子树也都不存在。

题目目的:

  1. 理解二叉树的结构:掌握二叉树的基本概念,包括节点、先序遍历、左子树和右子树。

  2. 学习先序遍历的特点:在先序遍历中,第一个节点是根节点,紧接着是左子树的遍历,最后是右子树的遍历。

  3. 实现字符串到二叉树的转换:通过解析先序遍历字符串,学会如何构建相应的二叉树数据结构。

  4. 掌握递归思想:在构建二叉树和遍历输出二叉树时,使用递归方法解决问题。

  5. 提高编程能力:通过实际编写代码,提高编程技巧,特别是在处理指针和动态数据结构时。

  6. 锻炼算法实现能力:实现从字符串到树结构的转换,需要设计和实现有效的算法。

  7. 增强空间想象能力:通过文本形式输出二叉树,增强对树结构空间布局的理解。

  8. 学习数据结构的应用:了解如何将理论知识应用于实际问题,例如使用二叉树解决实际问题。

样例输出格式:

程序应该能够根据输入的先序遍历字符串,以文本形式输出对应的二叉树结构。输出格式应类似于:

    A
   / \
  ST  C
     / \
    D 10
   /
  G
 /
F

每一层的缩进表示树的层次结构,每个节点后没有空格,且每个节点正确地与其子节点对齐。

注意事项:

  • 输入字符串中的节点数据长度不超过3,且节点数据由字母和数字组成。
  • 输入字符串中的“#”代表空树,即没有子节点。
  • 输出格式要符合题目要求,特别是缩进和对齐。

实现一个简单的文本界面下的二叉树创建和遍历程序。
下面是对代码的详细解析:

  1. 头文件和命名空间

    • 包含 <bits/stdc++.h> 头文件,它包含了标准库中的大部分内容。
    • 使用 using namespace std; 来避免在标准库类型和函数前加 std::
  2. 全局变量

    • depth 用于记录当前的层级深度。
    • judge 用于判断输入是否结束,并跳出循环。
  3. 结构体定义

    • tr 结构体定义了二叉树的节点,包含一个 string s 存储节点数据,以及两个指向左右子节点的指针 LCRC
  4. 递归创建节点

    • Creattr 函数用于递归创建二叉树的节点。
    • 读取节点数据,如果输入的是 # 表示结束,否则递归创建左子树和右子树。
  5. 递归创建树

    • CreatTree 函数用于递归创建整个二叉树。
    • 读取根节点数据,如果读取失败(文件结束或空字符串),设置 judge 为 1 并返回 0 表示结束。
  6. 递归输出节点

    • Outtr 函数用于递归输出二叉树的节点。
    • 首先递归输出右子树,然后输出当前节点(带缩进表示层级),最后递归输出左子树。
  7. 输出树

    • OutTree 函数调用 Outtr 函数输出二叉树。
  8. 主函数 main

    • 使用 while(1) 创建无限循环,直到 judge 被设置为 1 时跳出。
    • 创建 Tree 指针,调用 CreatTree 函数创建二叉树。
    • 如果 judge 为 1,使用 break 跳出循环。
    • 调用 OutTree 函数输出二叉树,并输出一个空行。
  9. 程序结束

    • 返回 0,表示程序正常结束。

代码逻辑分析

  • 这段代码使用递归方法来创建和遍历二叉树。
  • 使用 # 作为输入结束的标志,允许用户输入空格跳过节点的创建。

潜在问题

  • 使用 cin 直接读取字符串可能不是最佳选择,特别是在处理空格和特殊字符时。
  • 代码没有释放动态分配的内存,可能导致内存泄漏。

改进建议

  • 考虑使用 getline(cin, m->s) 来读取包含空格的字符串。
  • 在程序结束时,添加代码来释放所有动态分配的内存。
  • 可以考虑使用异常处理来管理输入错误和程序错误。
  • 为了提高代码的健壮性,可以添加对输入有效性的检查。

部分实现

存储节点数据

typedef struct tr{
    string s;
    struct tr *LC;
    struct tr *RC;
}tr,*Tr;

2.递归创建二叉树的节点

void Creattr(Tr &m){//建立节点 
    m=new tr;
    cin>>m->s;
    if(m->s[0]=='#');
    else {
    Creattr(m->LC);
    Creattr(m->RC);}
}

递归创建整个二叉树

int CreatTree(Tr &Tr1){//建立树 
    Tr1=new tr;
    cin>>Tr1->s;
    if(!(Tr1->s[0])){judge=1;return 0; }
    Creattr(Tr1->LC);
    Creattr(Tr1->RC);
    return 1;
}

递归输出二叉树的节点

void Outtr(Tr n){//输出节点 
    depth++;
    if(n->s[0]=='#');
    else {
    Outtr(n->RC);
    for(int i=0;i<depth;i++)printf("    ");
    cout<<n->s<<endl;
    Outtr(n->LC);}
depth--;
}

调用 Outtr 函数输出二叉树

void OutTree(Tr Tr2){//输出树 
    Outtr(Tr2->RC);
    cout<<Tr2->s<<endl;
    Outtr(Tr2->LC);
}

AC代码

#include<bits/stdc++.h>
using namespace std;
int depth=0;int judge=0;
//depth记录当前层数,判断空格的输入,judge判断输入是否结束,跳出循环 
typedef struct tr{
    string s;
    struct tr *LC;
    struct tr *RC;
}tr,*Tr;
void Creattr(Tr &m){//建立节点 
    m=new tr;
    cin>>m->s;
    if(m->s[0]=='#');
    else {
    Creattr(m->LC);
    Creattr(m->RC);}
}
int CreatTree(Tr &Tr1){//建立树 
    Tr1=new tr;
    cin>>Tr1->s;
    if(!(Tr1->s[0])){judge=1;return 0; }
    Creattr(Tr1->LC);
    Creattr(Tr1->RC);
    return 1;
}
void Outtr(Tr n){//输出节点 
    depth++;
    if(n->s[0]=='#');
    else {
    Outtr(n->RC);
    for(int i=0;i<depth;i++)printf("    ");
    cout<<n->s<<endl;
    Outtr(n->LC);}
depth--;
}
void OutTree(Tr Tr2){//输出树 
    Outtr(Tr2->RC);
    cout<<Tr2->s<<endl;
    Outtr(Tr2->LC);
}
int main(){
while(1){
    Tr Tree;
    CreatTree(Tree);
    if(judge==1)break;
    OutTree(Tree);
    cout<<endl;
}
    return 0;
}
  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值