如何使用Python将二叉树转换为Newick树?

时间:2020-04-09 08:38:25

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

我创建了一个具有以下结构的Tree对象:

class Tree:

    def __init__(self, data=None):
        self.data = data
        self.left_child = None
        self.right_child = None

此对象的一个​​实例是:

tree = Tree("A")
tree.left_child = Tree("B")
tree.right_child = Tree("C")
tree.left_child.left_child = Tree("D")
tree.left_child.right_child = Tree("E")
tree.right_child.left_child = Tree("F")
tree.right_child.right_child = Tree("G")

Newick format应该为((G,F)C,(E,D)B)A;

如何将Tree对象的任何实例转换为其Newick格式?

2 个答案:

答案 0 :(得分:0)

感谢Blckknght的提示。

def to_newick(tree):
    newick = ""
    newick = traverse(tree, newick)
    newick = f"{newick};"
    return newick

def traverse(tree, newick):
    if tree.left_child and not tree.right_child:
        newick = f"(,{traverse(tree.left_child, newick)}){tree.data}"
    elif not tree.left_child and tree.right_child:
        newick = f"({traverse(tree.right_child, newick)},){tree.data}"
    elif tree.left_child and tree.right_child:
        newick = f"({traverse(tree.right_child, newick)},{traverse(tree.left_child, newick)}){tree.data}"
    elif not tree.left_child and not tree.right_child:
        newick = f"{tree.data}"
    else:
        pass
    return newick

答案 1 :(得分:0)

我只是想您可能想要一些不递归的东西,所以迭代实现通常运行得更快。

from typing import List

class Tree:
    def __init__(self, data=None):
        self.data: str = data
        self.left_child: Tree = None
        self.right_child: Tree = None

    def newick(self) -> str:
        # Recursive version
        # Practically a postorder tree traversal
        if not self.left_child and not self.right_child:
            return self.data
        left_child = self.left_child.newick() if self.left_child else ""
        right_child = self.right_child.newick() if self.right_child else ""
        return f"({right_child},{left_child}){self.data}"

    def newick_iter(self) -> str:
        # Iterative version
        # https://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/
        res: str = ""
        traverse_stack: List[Tree] = []
        curr: Tree = self
        while True:
            while curr:
                if curr.left_child:
                    traverse_stack.append(curr.left_child)
                    res += '('

                traverse_stack.append(curr)
                curr = curr.right_child

            curr = traverse_stack.pop()
            if curr.left_child and (traverse_stack and curr.left_child == traverse_stack[-1]):
                tmp = traverse_stack.pop()
                traverse_stack.append(curr)
                curr = tmp
                if res[-1] == ')':
                    res = res[:-1]
                res += ','
            else:
                res += curr.data + ')'
                curr = None

            if not traverse_stack:
                break
        res = res[:-1]

        return res


def main():
    tree = Tree("A")
    tree.left_child = Tree("B")
    tree.right_child = Tree("C")
    tree.left_child.left_child = Tree("D")
    tree.left_child.right_child = Tree("E")
    tree.right_child.left_child = Tree("F")
    tree.right_child.right_child = Tree("G")

    print(tree.newick_iter())
    print(tree.newick())


if __name__ == '__main__':
    main()