[DS][Tree][PAT][List Leaves]

网易云课堂浙大数据结构课

第三周 树(上)

PAT: List Leaves解答

原题在这里

  • 关键问题
    1. 如何根据输入创建树?
    2. 如何根据建好的二叉树找出叶子节点?且顺序为从上到下,从左到右?
  • 如何根据输入创建树?
    1. 题目先输入N (N<=10),表示有个结点,节点数字从0到N-1编号;
    2. 然后从编号为0的结点到N-1,依次输入每个结点的左孩子编号和右孩子编号,没有某孩子则输入-, 将孩子信息记录到两个数组l[10]和r[10]中;当某个编号i出现时,就将findRoot[i]置为1(后面解释这一点);
    3. 这里的关键是找到根结点的编号!
      找到根结点的编号后,就可以依据l[10]和r[10]创建树,采用先序、中序、后序和层序我觉得都可以,我采用了先序。
    4. 通过观察发现(好吧,这句话有点坑,但是的确是我走在回宿舍的路上突然发现的),第2步输入左右孩子信息的时候,不会出现根结点的编号!(画出原题给的示例的树,会发现3是根结点,而3不会出现在输入里)所以可以遍历数组findRoot找到没出现的那个数字,也就数组findRoot中唯一为0的那个数字(在0到N-1之间),这个数字就是根结点的编号
    5. 找到根结点就可以愉快的去创建树了,但是注意分配内存和释放内存,注意一些小细节
void LevelOrderCreateBiTree(BiTree &BT, char num)
{
    BT = (BiTree)malloc(sizeof(TreeNode));
    if (num != '-') {
        BT->Data = num;
    } else {
        free(BT);
        BT = NULL;
        return;
    }
    LevelOrderCreateBiTree(BT->Left, l[num]);
    LevelOrderCreateBiTree(BT->Right, r[num]);
}
  • 如何根据建好的二叉树找出叶子节点?且顺序为从上到下,从左到右?
    这个何老师在MOOC上讲过了,很简单。
    1. 要找出叶子结点,只要在某种遍历方式中,处理结点的时候(例如print),加个条件(左右孩子均空才处理)就行了,因为只有叶子结点的左右孩子都是空的;
    2. 要从上到下,从左到右打印叶子结点,思考一下就会发现层序遍历方式符合要求,所以这里采用层序遍历的方式打印叶子结点。
void LevelOrderPrintLeaves(BiTree BT)
{
    BiTree T;
    queue<BiTree> Q;
    Q.push(BT);
    while (!Q.empty()) {
        T = Q.front();
        Q.pop();
        if (!T->Left && !T->Right) {
            //print right space
            --cnt;
            if (cnt) {
                cout << T->Data << " ";
            } else {
                cout << T->Data << endl;
            }
        }
        if (T->Left) Q.push(T->Left);
        if (T->Right) Q.push(T->Right);
    }
}
  • 细节问题:如何让你的输出后面没有多余的空格?
    打印叶子结点的编号时,我估计大部分人会这样:
    cout << BT->Data << " ";
    但是这样会在最后一个叶子结点后打印多余的一个空格。
    我用变量cnt在输入时统计叶子结点的个数,也就是当左右孩子均为-时++cnt;
    if (l[i] == '-' && r[i] == '-') ++cnt;
    然后用cnt来控制打印叶子结点的格式。
    if (cnt) {
    cout << T->Data << " ";
    } else {
    cout << T->Data << endl;
    }

整体代码如下:

#include <iostream>
#include <queue>
#include <cstdlib>

using namespace std;

typedef int ElementType;
typedef struct TreeNode* BiTree;
struct TreeNode {
    ElementType Data;
    BiTree Left;
    BiTree Right;
};
int findRoot[10] = { 0 }; // in order to find root's number
char l[10]; //record input data
char r[10]; //record input data
int cnt = 0; // in order to print right space;

void LevelOrderCreateBiTree(BiTree &BT, char num);
void LevelOrderPrintLeaves(BiTree BT);
void PreOrderPrinLeaves(BiTree BT);

int main()
{
    //input data
    int N;
    cin >> N;
    for (int i = 0; i != N; ++i) {
        cin >> l[i] >> r[i];
        if (l[i] != '-') {
            l[i] = l[i] - '0';
            findRoot[l[i]] = 1;
        }
        if (r[i] != '-') {
            r[i] = r[i] - '0';
            findRoot[r[i]] = 1;
        }
        //in order to print right space
        if (l[i] == '-' && r[i] == '-') ++cnt;
    }
    //find root's number
    //explanation: root's number will not occur in the input.
    //e.g.: as the web shows, 3 is root, but not occurs in the input.
    int root = 0;
    for (int i = 0; i != N; ++i) {
        if (0 == findRoot[i]) {
            root = i;
            break;
        }
    }
    //create binary tree
    BiTree BT;
    LevelOrderCreateBiTree(BT, root);
    //list leaves
    LevelOrderPrintLeaves(BT);
    //debug info:
    //PreOrderPrinLeaves(BT);
    //cout << "debug info" << endl;
    return 0;
}

void LevelOrderCreateBiTree(BiTree &BT, char num)
{
    BT = (BiTree)malloc(sizeof(TreeNode));
    if (num != '-') {
        BT->Data = num;
    } else {
        free(BT);
        BT = NULL;
        return;
    }
    LevelOrderCreateBiTree(BT->Left, l[num]);
    LevelOrderCreateBiTree(BT->Right, r[num]);
}
void LevelOrderPrintLeaves(BiTree BT)
{
    BiTree T;
    queue<BiTree> Q;
    Q.push(BT);
    while (!Q.empty()) {
        T = Q.front();
        Q.pop();
        if (!T->Left && !T->Right) {
            //print right space
            --cnt;
            if (cnt) {
                cout << T->Data << " ";
            } else {
                cout << T->Data << endl;
            }
        }
        if (T->Left) Q.push(T->Left);
        if (T->Right) Q.push(T->Right);
    }
}
void PreOrderPrinLeaves(BiTree BT)
{
    if (BT) {
        cout << BT->Data << " ";
        PreOrderPrinLeaves(BT->Left);
        PreOrderPrinLeaves(BT->Right);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值