使用堆栈将字符串解析为树

时间:2013-02-10 02:13:10

标签: python recursion tree stack

为了完全披露,此 HW,但转让已经到期。

如果我们按如下方式定义一个简单的树:

class Tree (object):
    __slots__ = "node","children"
    def __init__(self,node,children=[]):
        self.node = node
        self.children = children

我们如何从字符串构建树?在字符串模型中,“NIL”表示树的结尾。因此,字符串1 2 5 NIL 3 4 NIL NIL NIL NIL将返回一个类似t = Tree(1, [Tree(2, [Tree(5, []), Tree(3, [Tree(4)])])])的树。该解决方案可以使用递归和/或堆栈。我以为我理解堆栈和递归,但我无法弄清楚这个问题。有什么想法吗?

修改
要添加更多信息,我们可以打印树,如:

def __str__(self):
    return "(%s)" % " ".join(map(str,[self.node]+self.children))

我无法接近创建树并打印它。我能想到的只是创建一个看起来像字符串的字符串来创建一个树。我有:

def delinearize(self, linear_string):
    @staticmethod
    tree_data = linear_string.split()
    tree_str = ""
    if tree_data[0] == "NIL":
        print "Tree needs initial root node"
        return
    for entry in tree_data:
        if entry != "NIL":
                tree_str += "Tree("+entry+", ["
        elif entry == "NIL":
                tree_str += "]),"

3 个答案:

答案 0 :(得分:2)

在您的示例中,对于此输入:

1 2 5 NIL 3 4 NIL NIL NIL NIL

你说这应该是结果(注意我刚刚格式化你的版本以便于理解):

Tree(1, [
    Tree(2, [
        Tree(5, []),
        Tree(3, [
            Tree(4)
        ])
    ])
])

“看起来像”这个:

  1
  |
  2
 / \
5   3
    |
    4

从这个(和nneonneo的有用评论)我们可以确定这些树是如何从字符串构建的。它看起来像这样:

  1. 从理论根节点开始,被视为“当前”节点。
  2. 对于每个非NIL值,将其添加为当前节点的子节点,并将其标记为新的当前节点。也就是说,下降。
  3. 对于每个NIL值,将当前节点的父节点标记为新的当前节点。也就是说,提升。
  4. 当再次达到理论根节点时,我们就完成了(并且字符串应该被完全消耗)。
  5. 请注意,如果要节省空间,可能会省略返回根目录的尾随NIL。另一方面,包括他们支持最后的健全检查。

    根据我上面给出的大纲,它可以以迭代方式实现,没有递归。有些人更喜欢递归解决方案,但无论哪种方式同样强大,所以后者留作练习!

答案 1 :(得分:0)

所以,让我们说我们知道以下两件事:

  • 如果您从输入字符串中读取NIL,则表示您已读取并清空树。
  • 如果您读取了一个数字,那么您有一个非空树,其根包含所述数字,您仍然需要从输入字符串中读取两个树(一个用于左子,一个用于右子)。

现在我们已经准备好阅读树了:)。假设有以下类似C的结构(我允许你在python中做这个练习,并且在python中更干净):

struct tree {
   int value;
   tree *left;
   tree *right;
}

并且有些人挥手基本上是一个接受char *的方法,返回第一个标记并将输入字符串更改为指向下一个标记)在输入流处可以执行:

tree *readTree(char *&inputString) {
   char *token = read_next_token(inputString); 
   if (strcmp(token, "NIL") {
      // empty tree .. we return
      return NULL;
   }

   struct tree* node = malloc(sizeof(struct tree));
   node->value = token_as_int(token);

   // note that after the readTree is called the inputString will be modified
   // that's why i defined it to take a reference to a pointer of chars.
   node->left = readTree(inputString);
   node->right = readTree(inputString);
   return node; 
}

并且read_next_token定义为:

char *read_next_token(char*&inputString) {
  char *token = inputString;

  while ( *inputString != ' ' )
    inputString++;

  *inputString = 0; // make the token a null terminated string.

  while ( *inputString == ' ' ) inputString++;

  return token;
}

答案 2 :(得分:0)

也许是这样的:

#! /usr/bin/python3.2

class Tree:
    def __init__ (self, value):
        self.value = value
        self.parent = None
        self.children = []

    def __iadd__ (self, child):
        child.parent = self
        self.children.append (child)
        return self

    def fromString (string):
        return Tree.fromList (string.split () ) [0]

    def fromList (list):
        node = Tree (list [0] )
        list = list [1:]
        while list [0] != 'NIL':
            child, list = Tree.fromList (list)
            node += child
        return node, list [1:]

    def __repr__ (self):
        return '{}{}'.format (self.value, ': {}'.format (self.children) if self.children else '')

t = Tree.fromString ('1 2 5 NIL 3 4 NIL NIL NIL NIL')
print (t)

t = Tree.fromString ('1 2 NIL 3 4 NIL 5 NIL 6 NIL NIL 7 NIL NIL')
print (t)