【问题标题】:Building a binary tree from a string从字符串构建二叉树
【发布时间】:2019-10-18 02:52:43
【问题描述】:

我正在尝试从字符串构建一棵树。该字符串的形式为:((. (.A.E))(.I.O)),其中树的 5 个叶节点用句点表示。

我无法确定如何解决这个问题;我已尝试针对此网站上提供的类似问题调整解决方案:https://www.geeksforgeeks.org/construct-binary-tree-string-bracket-representation/

在我准备编码面试时,非常感谢您提供的任何帮助。

谢谢!

【问题讨论】:

  • 图片不代表BST,它只是一棵树。 'Z' 不小于'A',除非您将树倒序排列,但'n''A' 不会倒序排列。
  • 抱歉——澄清一下,这只是一棵树;问题的想法更多只是将字符串序列转换为树
  • 好吧,这更有意义,因为“二叉搜索树”(或 BST)是一种非常特殊的树,具有非常特殊的排序要求。你卡在哪一部分?他们没有讨论的唯一微妙之处是从他们用来跟踪打开和关闭'('')' 的堆栈中推送和弹出。其余的应该是相当直截了当的。另外,在这里寻求帮助,您需要发布A Minimal, Complete, and Verifiable Example (MCVE)。否则,我们只是在猜测您卡在哪里。

标签: c++ recursion tree binary-tree binary-search-tree


【解决方案1】:

在我看来,只有一些规则需要遵守。根据正在处理的字符,您有以下选项:

  1. 如果是“(”,则表示您必须根据您在此之前采取的操作,将树构建得更深,向左或向右
  2. 如果是“.”,则应读取字符串中的下一个元素以确定节点值,然后在递归中返回一个“。”。代表一片叶子
  3. 如果是“)”,则表示您已完成构建节点的子树,因此您必须再次返回递归中的一步

关于如何实现的一些建议:

  1. 编写一个以字符串为输入的递归函数
  2. 该函数还应返回一个字符串,该字符串表示仍有待进一步处理的字符串
  3. 如果在任何步骤中您的字符串为空,则表示要处理的字符串无效
  4. 每次构建完节点的左子树或右子树时,都应检查“)”

希望这对您的面试有所帮助并祝您好运!

【讨论】:

  • "写一个以字符串为输入的递归函数"??这部分不清楚。 (以及未说明递归调用的退出条件和目标的可疑建议)
  • 谢谢!我一直在尝试实现这一点,但想知道您是否可以通过“基于您在此之前采取的行动”更深入地构建树来澄清您的意思——我将如何确定这一点?在叶子和)的情况下,“在递归中返回一步”是什么意思?如果您不介意对此进行伪编码,那将非常有帮助!我已经盯着这个看了好几个小时了,一直没能想出一个可行的解决方案——我尝试了我问题链接中的那个,但没能做出相应的调整。
【解决方案2】:

我想出的解决方案是基于堆栈的迭代解决方案。它有一些规则要遵循:

  1. 将任何东西推送到堆栈中
  2. 如果遇到堆栈的),请开始删除元素,直到遇到(,然后也将其弹出。
  3. 在步骤 2 中弹出元素时,将它们存储在向量中,)( 除外。
  4. 创建一个树节点并将父节点的子节点标记为向量中的所有元素。
  5. 将父节点推回堆栈。

让我们看看你的例子: S = "((a($Z))(An))",为了清楚起见更改了 ' ' -> 'a'

注意:堆栈向右增长。

Stack["((a($Z"]
encounter ')'
Stack["((a"], vector<"Z$">
reverse vector -> vector<"$Z">
Parent Node -> N(id='1'), children -> <N(id='$'), N(id='Z')>
push N(1) to stack

Stack["((a1]
encounter ')'
Stack["("], vector<"1a">
reverse vector -> vector<"a1">
Parent Node -> N(id='2'), children -> <N(id='a'), N(id=1)>
push N(2) to stack

Stack["(2(An"]
encounter ')'
...

您可以继续此操作以达到顶峰。完成后,即字符串已用完,您将在堆栈中只剩下一个元素,这将是您的父元素或树的根。

代码:

Node* solve(string s) {
    stack<Node *> st;
    int idx = 0, rt = 1;
    while (idx < s.size()) {
        Node *n = get_node(s[idx]);
        st.push(n);
        ++idx;

        if (st.top()->v == ')') {
            st.pop();
            vector<Node *> child;
            while (st.size() && st.top()->v != '(') {
                child.push_back(st.top()); st.pop();
            }
            if (st.top()->v == '(') st.pop();

            Node *par = get_node('0' + rt++);
            reverse(child.begin(), child.end());
            for (Node *t : child) {
                t->parent = par;
                par->child.push_back(t);
            }
            st.push(par);
        }
    }
    return st.top();
}

Full Working code

这段代码是一个通用的实现,所以任何节点都可以有尽可能多的孩子,所以 n 叉树构造。 例如:

input: ((a($Zk))(An))
output:
Parent: 4: 2 3
Parent: 2: a 1
Parent: 3: A n
Parent: 1: $ Z k

【讨论】:

  • 非常感谢@pikaynu,这很有帮助。我正在尝试找到一种方法来递归地执行此操作,因此,如果您对此有任何提示,我将不胜感激!
猜你喜欢
  • 2021-11-23
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多