文本模式显示二叉树

                            A
                _____/  \_____
              /                          \
            B                              C
        _/  \_                      _/  \_
      /          \                  /          \
    D              E              F              G
                      \
                        H

文本显示Python版本

class BinTreeHelper(object):

    def __init__(self, root, data_key="data", lchild_key="lchild", rchild_key="rchild"):
        self.root = root
        self.data_key = data_key
        self.lchild_key = lchild_key
        self.rchild_key = rchild_key

    @staticmethod
    def print_not_enter(s):
        print(s, end="")

    def get_lchild(self, node):
        return getattr(node, self.lchild_key)

    def get_rchild(self, node):
        return getattr(node, self.rchild_key)

    def get_data(self, node):
        return getattr(node, self.data_key)

    def get_depth(self):
        def _get_depth(node, depth):
            lchild = self.get_lchild(node)
            rchild = self.get_rchild(node)
            left_depth = _get_depth(lchild, depth + 1) if lchild else depth
            right_depth = _get_depth(rchild, depth + 1) if rchild else depth
            return max((left_depth, right_depth))

        return _get_depth(self.root, 1)

    def display_in_text(self):
        root = self.root
        queue = list()
        nhigth = self.get_depth()
        END = "LEVEL_END"
        queue.append(root)
        queue.append(END)
        d = nhigth
        while d >= 1:
            na = 1
            for j in range(0, d - 1):  # 计算2n-1
                na *= 2
            # 第一步:输出每层结点的数据域
            while True:
                p = queue.pop(0)  # 从队头取出一个结点p
                queue.append(p)  # 结点放回到队尾,因此结点可重复提取
                if p == END:
                    break
                for j in range(0, 2 * na - 2):  # 输出2n+1-2个空格
                    self.print_not_enter(" ")
                self.print_not_enter(self.get_data(p) if p else " ")  # 输出结点数据或空格
                for j in range(0, 2 * na + 1):  # 输出2n+1+1个空格
                    self.print_not_enter(" ")
            print("")  # 一层的结点数据输出结束,回车
            if d == 1:  # 如果是最后一层,不用输出下面的链接字符
                break

            # 第二步:输出每层结点与其子结点的第一行链接字符
            while True:  # 循环直至一层结束
                p = queue.pop(0)  # 从队头取出一个结点p
                queue.append(p)  # 结点放回到队尾,因此结点可重复提取
                if p == END:
                    break
                # 输出2n个空格或2n- 1(倒数第二层)个空格
                for j in range(0, na if d != 2 else na - 1):
                    self.print_not_enter(" ")

                p_and_left_exist = p and self.get_lchild(p)
                p_and_right_exist = p and self.get_rchild(p)
                # 为左子结点连接符输出’_’或空格
                for j in range(0, na - 3):
                    self.print_not_enter("_" if p_and_left_exist else " ")
                self.print_not_enter("/" if p_and_left_exist else " ")  # 为左子结点连接符输出’/’或空格
                self.print_not_enter(" ")
                self.print_not_enter("\\" if p_and_right_exist else " ")  # 为右子结点连接符输出’\’或空格
                # 为右子结点连接符输出’_’或空格
                for j in range(0, na - 3):
                    self.print_not_enter("_" if p_and_right_exist else " ")
                # 输出2n+3个空格或2n+ 2(倒数第二层)个空格
                for j in range(0, na + 3 if d != 2 else na + 2):
                    self.print_not_enter(" ")
            print("")  # 结点数据下面的连接符输出结束,回车
            # 第三步:输出每层结点与其子结点的第二行链接字符
            if d != 2:
                while True:
                    p = queue.pop(0)  # 从队头取出一个结点p
                    queue.append(p)  # 结点放回到队尾,因此结点可重复提取
                    if p == END:
                        break
                    for j in range(0, na - 1):
                        self.print_not_enter(" ")  # 输出2n-1个空格
                    p_and_left_exist = p and self.get_lchild(p)
                    p_and_right_exist = p and self.get_rchild(p)
                    self.print_not_enter("/" if p_and_left_exist else " ")  # 为左子结点连接符输出’/’或空格
                    for j in range(0, 2 * na - 3):
                        self.print_not_enter(" ")  # 输出2n+1-3个空格
                    self.print_not_enter("\\" if p_and_right_exist else " ")
                    for i in range(0, na + 2):
                        self.print_not_enter(" ")  # 输出2n+2个空格
                print("")  # 结点数据下面的第二层连接符输出结束,回车

            # 第四步:更新队列中的结点,即把队列中的结点换成下一层的结点
            while True:  # 更新队列的循环体
                p = queue.pop(0)
                if p == END:
                    break
                queue.append(self.get_lchild(p) if p else None)
                queue.append(self.get_rchild(p) if p else None)
            queue.append(END)

            d -= 1


class Node(object):
    def __init__(self, data, left_node=None, rigth_node=None):
        self.data = data
        self.left_child = left_node
        self.right_child = rigth_node


if __name__ == "__main__":
    root = Node("A", Node("B", Node("D"), Node("E", None, Node("H"))), Node("C", Node("F"), Node("G")))
    btH = BinTreeHelper(root, lchild_key="left_child", rchild_key="right_child")
    t = btH.display_in_text()

参考文献:
[1]  江顺亮  任燕《电脑知识与技术:学术交流》二叉树结构的文本模式显示  2012