【问题标题】:Python - Converting an n-ary tree to a binary treePython - 将 n 叉树转换为二叉树
【发布时间】:2014-03-27 02:56:35
【问题描述】:
class Tree:

        def __init__(self, new_key):
    self.__key = new_key    # Root key value
    self.__children = []     # List of children
    self.__num_of_descendants = 0 # Number of Descendants of this node    

# Prints the given tree
def printTree(self):
    return self.printTreeGivenPrefix("", True)   

# Prints the given tree with the given prefix for the line
# last_child indicates whether the node is the last of its parent"s child
# or not
def printTreeGivenPrefix(self, line_prefix, last_child):
    print(line_prefix, end="")
    if last_child:
        print("â””--> ", end="")
    else:
        print("|--> ", end="")
    print(self.__key)

    if len(self.__children) > 0:
        next_pre = line_prefix
        if last_child:
            next_pre += "     "
        else:
            next_pre += "|    "
        for child_index in range(len(self.__children)-1):
            self.__children[child_index].\
                printTreeGivenPrefix(next_pre, False)
        self.__children[-1].printTreeGivenPrefix(next_pre, True)

def __repr__(self):
    return "[" + str(self.__key) + "".join(
        [ repr(child) for child in self.__children ]) + "]"

# This static function will load a tree with the format of below:
# [root[child_1][child_2]...[child_n]]
# Each child_i can be a tree with the above format, too
# pos is the position in the given string
@staticmethod
def loadTree(tree_str, pos = 0):
    new_node = None
    while pos < len(tree_str):
        if tree_str[pos] == "[":
            pos += 1
            new_node = Tree(tree_str[pos])
            while pos < len(tree_str) and tree_str[pos + 1] != "]":
                pos += 1
                child_tree, pos = Tree.loadTree(tree_str, pos)
                if child_tree:
                    new_node.__children.append(child_tree)
                    new_node.__num_of_descendants += \
                        1 + child_tree.__num_of_descendants
            return new_node, pos + 1
        else:
            pos += 1
    return new_node, pos

def find_largest(self):
    if self.__num_of_descendants == 1:
        return self.__children[0]

    else:
        largest_child = self.__children[0]
        for child in self.__children:
            if child.__num_of_descendants > \
               largest_child.__num_of_descendants:
                largest_child = child
            if child.__num_of_descendants == \
               largest_child.__num_of_descendants:
                if child.__key > largest_child.__key:
                    largest_child = child
    return largest_child

def convert_to_binary_tree(self):
    if self.__num_of_descendants != 0:
        if self.__num_of_descendants < 3:
            for child in self.__children:
                child.convert_to_binary_tree()

        if self.__num_of_descendants > 2:
            left_child = self.__children[0]
            for child in self.__children[1:]:
                if len(child.__children) > len(left_child.__children):
                    left_child = child
                elif len(child.__children) == len(left_child.__children):
                    if child.__key > left_child.__key:
                        left_child = child
            self.__children.remove(left_child)
            self.__num_of_descendants -= 1

            right_child = self.__children[0]
            for child in self.__children[1:]:
                if len(child.__children) > len(right_child.__children):
                    right_child = child
                elif len(child.__children) == len(right_child.__children):
                    if child.__key > right_child.__key:
                        right_child = child
            self.__children.remove(right_child)
            self.__num_of_descendants -= 1
            print(self.__num_of_descendants)
            print(self.__children)
            print(left_child)
            print(right_child)

            #Move remaining children two either left_child or right_child.
            while self.__num_of_descendants != 0:
                largest_child = self.find_largest()
                print(largest_child)
                if left_child.__num_of_descendants < \
                   right_child.__num_of_descendants:
                    left_child.__children.append(largest_child)
                    left_child.__num_of_descendants += 1
                    self.__children.remove(largest_child)
                    self.__num_of_descendants -= 1                        

                elif left_child.__num_of_descendants > \
                   right_child.__num_of_descendants:
                    right_child.__children.append(largest_child)
                    right_child.__num_of_descendants += 1
                    self.__children.remove(largest_child)
                    self.__num_of_descendants -= 1                        

                elif left_child.__num_of_descendants == \
                   right_child.__num_of_descendants:
                    if left_child.__key > right_child.__key:
                        left_child.__children.append(largest_child)
                        left_child.__num_of_descendants += 1
                        self.__children.remove(largest_child)
                        self.__num_of_descendants -= 1                            
                    else:
                        right_child.__children.append(largest_child)
                        right_child.__num_of_descendants += 1
                        self.__children.remove(largest_child)
                        self.__num_of_descendants -= 1
            #Now run recursion on left and right binary children.
            self.__children.append(left_child)
            self.__children.append(right_child)
            self.__num_of_descendants = 2
            print(self.__children)
            for child in self.__children:
                child.convert_to_binary_tree()
def main():
    tree, processed_chars = Tree.loadTree('[z[y][x][w][v]]]')
    tree.convert_to_binary_tree()
    tree.printTree()
    print(tree)

if __name__ == "__main__":
    main()

我必须将给定的树转换为二叉树。如果树中的一个节点有两个以上的孩子,我必须将具有最多后代的孩子分配为左节点,将具有第二多后代的孩子分配为右孩子。剩余的孩子添加如下: 1)取后代数量最多的孩子 2)将其添加到左/右节点。那个时候孩子少的那个。

*如果任何时候我需要选择后代数量最多的孩子,但是有两个+后代数量相同,我就取key值较大的那个。

I get a print out like this...
2 #Number of 'z' children after left and right node chosen.
[[w], [v]] #Children of 'z'
[y] #Binary left child of 'z'
[x] #Binary right child of 'z'
[w] #This is a bug. It should be choosing 'v' as larger child of 'z' and assigning it to left child 'y'
[v] #This is a bug. see above.
[[y[w]], [x[v]]] #These are the children of node 'z'
â””--> z #schematic of binary tree
     |--> y
     |    â””--> w
     â””--> x
          â””--> v
[z[y[w]][x[v]]] #final binary tree 

【问题讨论】:

  • 旁白:这里没有理由在你的变量前面加上__。如果你坚持,你可以使用_ 作为友好的提醒,有些内容不打算在课堂外修改,但即使这样也常常是矫枉过正。
  • 是的,我也不喜欢他们的名字,但我的导师坚持...
  • 你能检查一下代码的缩进吗? main 函数和 if __name__ == "__main__" 样板是否真的缩进在 class 之下,或者它们实际上是在顶层?
  • 好吧,如果有三个以上的子节点,则必须重新排列子节点。也就是说,如果一个节点有三个孩子,则将最大的两个值分配为该节点的左孩子和右孩子,而其余的孩子则分配给新的左孩子或右孩子。如果节点只有两个子节点,则它已经是二叉树格式,不需要做任何事情。但是,我想对这 2 个孩子进行格式化,以防其中一个有 3 个以上的孩子。
  • 抱歉,缩进已关闭。 main 函数,如果 name == "main" 在 main 级别。

标签: python python-3.x tree binary-tree


【解决方案1】:

DSM 的评论帮助我了解了情况。在 convert_to_binary_tree 方法的第一部分中选择 left_childright_child 后,您不会将它们从子列表中删除。这意味着稍后,当您将当前节点的所有子节点添加到新父节点时,您会将左右子节点添加到它们自己(或彼此)。当你递归到这些孩子时,你最终可能会无限循环。

我不太了解您的left_childright_child 选择的逻辑,所以我没有固定的代码建议您。一个快速但丑陋的解决方法是将 if child in (left_child, right_child): continue 语句放在 for 循环的顶部,您将在其中将其他孩子分配给新父母。

请注意,您当前的代码中还有另一个错误,即左右子代的后代计数将不正确。那是因为当您将他们的一些前兄弟姐妹作为孩子推入他们时,您并没有更新计数。

【讨论】:

  • 您好,感谢您花时间查看代码。在意识到你刚刚发布的内容后,我最终刮掉了大部分内容。我更新了我的代码,但是,由于某种原因,我仍然遇到了一个错误。如果您有时间,请查看更新的帖子:)
  • 我已经缩小了范围。无论出于何种原因程序进入 def find_largest(self): if child.__key > maximum_child.__key: maximum_child = child 它没有注册 v > w.
猜你喜欢
  • 2012-02-28
  • 1970-01-01
  • 2020-08-24
  • 2021-06-07
  • 1970-01-01
  • 2011-07-24
  • 2015-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多