7-10 重建二叉树 (10 分)

80 篇文章 7 订阅
77 篇文章 11 订阅

给定二叉树的中根序列和后根序列,请编写程序创建该二叉树,计算其高度和先根序列,最后删除该二叉树;如给定的中根和后根序列不合法,则亦能识别。

输入格式:
输入为两行字符串,第一行表示某二叉树的后根序列,第二行表示其中根序列。结点的值均为A-Z的大写字母,故二叉树结点个数不超过26,且保证输入的两个序列都是结点的全排列,但不一定是合法的中根和后根序列。

输出格式:
如果输入的序列不合法(不是同一棵树的中根序列和后根序列),则输出INVALID。若输入序列合法,输出为两行,第一行为一个整数,表示该二叉树的高度,第二行为一个字符串,表示该二叉树的先根序列。

输入样例1:

CEFDBHGA
CBEDFAGH

输出样例1:

3
ABCDEFGH

输入样例2:

CBEDFAGH
CEFDBHGA

输出样例2:

INVALID

输入样例3:

BCA
CAB

输出样例3:

INVALID

代码有点冗长感觉T_T 注意求树高那里减一,不能按之前学的来
#include <iostream>
using namespace std;

typedef struct Node {
    char data;
    struct Node *left, *right;
} Node, *Tree;
//递归判断序列是否合法,若合法,则左右子树结点个数和相应字符也应该相等
bool judge(string a, string b) { 
    if (a.length() == 0 && b.length() == 0)
        return true;
    if (a.length() != b.length())
        return false;
    char ch = a[a.length() - 1];
    int i;
    for (i = 0; i < b.length(); i++) {
        if (ch == b[i])
            break;
    }
    string aleft = a.substr(0, i);
    string aright = a.substr(i, a.length() - 1 - i);
    string bleft = b.substr(0, i);
    string bright = b.substr(i + 1);
    for (i = 0; i < aleft.length(); i++) {
        if (bleft.find(aleft[i]) == -1)
            return false;
    }
    for (i = 0; i < aright.length(); i++) {
        if (bright.find(aright[i]) == -1)
            return false;
    }
    return judge(aleft, bleft) && judge(aright, bright);
}
//建立二叉树
Tree create(char *post, char *in, int n) {
    if (n < 1)
        return NULL;
    Tree tree = (Tree)malloc(sizeof(Node));
    tree->data = post[n - 1];
    tree->left = tree->right = NULL;
    int i;
    for (i = 0; i < n; i++) {
        if (post[n - 1] == in[i])
            break;
    }
    tree->left = create(post, in, i);
    tree->right = create(post + i, in + i + 1, n - i - 1);
    return tree;
}
//得到二叉树高度
int geth(Tree tree) {
    if (!tree)
        return 0;
    int left = geth(tree->left);
    int right = geth(tree->right);
    return (left > right ? left : right) + 1;
}
//先序遍历
void preorder(Tree tree) {
    if (!tree)
        return;
    printf("%c", tree->data);
    preorder(tree->left);
    preorder(tree->right);
}
//递归删除二叉树
void deletetree(Tree tree) {
    if (!tree)
        return;
    deletetree(tree->left);
    deletetree(tree->right);
    free(tree);
}

int main() {
    string a, b;
    cin >> a >> b;
    if (!judge(a, b))
        printf("INVALID");
    else {
        int n = a.length();
        char post[30], in[30];
        int p = 0;
        for (int i = 0; i < n; i++)
            post[p++] = a[i];
        p = 0;
        for (int i = 0; i < n; i++)
            in[p++] = b[i];
        Tree tree = create(post, in, n);
        printf("%d\n", geth(tree) - 1);//如果不减一,输出4,这个题应该是按照只有一个结点时,树高为0来的
        preorder(tree);
        deletetree(tree);
    }
    return 0;
}
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
还原二叉树是指二叉树的前序遍历和中序遍历结果,重建出原二叉树的过程。实现这个过程的关键是找到二叉树节点,然后再节点将左子树和右子树递归地还原。 首先,我们需要定义一个二叉树节点的类,包含节点值、左孩子节点和右孩子节点的属性。接下来,我们可以使用递归的方法来还原二叉树。 我们可以利用前序遍历的结果,找到二叉树节点。前序遍历结果的第一个元素就是节点的值。然后,我们可以在中序遍历结果中找到节点的位置,将中序遍历结果为左子树和右子树的部。 接下来,对于节点的左子树,我们可以用前序遍历结果和中序遍历结果的左子树部递归地还原左子树。同理,对于节点的右子树,我们可以用前序遍历结果和中序遍历结果的右子树部递归地还原右子树。 最后,我们将节点的左子树和右子树连接到节点上,就可以得到还原后的二叉树。 下面是一个简单的Python代码实现还原二叉树的过程: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def buildTree(preorder, inorder): if not preorder or not inorder: return None # 据前序遍历结果找到节点 root_val = preorder[0] root = TreeNode(root_val) # 在中序遍历结果中找到节点的位置,将左子树和右子树开 root_index = inorder.index(root_val) left_inorder = inorder[:root_index] right_inorder = inorder[root_index+1:] # 递归还原左子树和右子树 left_preorder = preorder[1:1+len(left_inorder)] right_preorder = preorder[1+len(left_inorder):] root.left = buildTree(left_preorder, left_inorder) root.right = buildTree(right_preorder, right_inorder) return root # 测试 preorder = [1, 2, 4, 5, 3, 6, 7] inorder = [4, 2, 5, 1, 6, 3, 7] root = buildTree(preorder, inorder) ``` 以上是还原二叉树的简单实现。这个方法的时间复杂度为O(n),其中n是二叉树节点的个数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值