Python 实现列表与二叉树相互转换并打印二叉树封装类-详细注释+完美对齐

# MyBinaryTree.py
# Python 实现列表与二叉树相互转换并打印二叉树封装类-详细注释+完美对齐
# by: ybmj@vip.163.com, QQ: 153248043, blog: https://www.cnblogs.com/ybmj/

from binarytree import build
import random


class MyBinaryTree:
    lst = []  # 二叉树列表
    lay_list = []  # 二叉树层列表
    node_list = []  # 二叉树节点列表

    def __init__(self, lst=[]):
        MyBinaryTree.lst = lst

    class TreeNode:
        def __init__(self, val=0, left=None, right=None):
            self.val = val
            self.left = left
            self.right = right

    # 从二叉树列表得到二叉树层列表
    def getLaylist(self):
        if MyBinaryTree.lay_list: return MyBinaryTree.lay_list

        if not MyBinaryTree.lst: return []  # 判断列表为空不能用 is None,必须用 not _list。判断变量为空才能用 is None

        lay = 0  # 层数
        loc = 0  # 节点列表当前位置
        len_all = len(MyBinaryTree.lst)  # 整个列表的长度
        while len_all > 0:
            len_lay = pow(2, lay)  # 该层列表的长度,每层的长度为 2^lay,2^0、2^1、2^2、2^3、...
            MyBinaryTree.lay_list.append(MyBinaryTree.lst[loc:(loc + len_lay)])  # 从 _list 切片得到该层的元素列表,添加到 lay_list 中
            loc += len_lay
            len_all -= len_lay
            lay += 1

        return MyBinaryTree.lay_list

    # 从二叉树层列表得到二叉树节点列表
    def getNodelist(self):
        if MyBinaryTree.node_list: return MyBinaryTree.node_list

        if not MyBinaryTree.lay_list: MyBinaryTree.lay_list = self.getLaylist()

        if not MyBinaryTree.lay_list: return []

        for i in range(len(MyBinaryTree.lay_list)):
            # 对 lay_list 的节点(每个节点元素都为列表)进行循环遍历,用列表中的每个元素构建TreeNode添加到node_list中
            for j in range(len(MyBinaryTree.lay_list[i])):
                # 转换层列表为:[[5], [2, 9], [10, 1, 10, 5], [0, 9, 1]]
                MyBinaryTree.node_list.append(
                    MyBinaryTree.TreeNode(MyBinaryTree.lay_list[i][j]))  # 将列表索引 j 元素构建TreeNode添加到node_list中

                # 为上一层的父节点 TreeNode 元素添加 left、或right 值
                # if lay_list[tail][j] and lay > 0:  # 在 python 中0、空都为假,非零为真,所以这样将导致 lay_list[tail][j] 为 0 时没能填充
                if MyBinaryTree.lay_list[i][j] is not None and i > 0:  # 必须改为这样,才能避免 lay_list[tail][j] 为 0 时没能填充
                    if j % 2 == 0:
                        MyBinaryTree.node_list[pow(2, i - 1) - 1 + j // 2].left = MyBinaryTree.node_list[-1]
                    else:
                        MyBinaryTree.node_list[pow(2, i - 1) - 1 + j // 2].right = MyBinaryTree.node_list[-1]

        return MyBinaryTree.node_list

    # 从二叉树节点列表得到二叉树列表
    def getListFromTree(self):
        if not MyBinaryTree.node_list:
            MyBinaryTree.node_list = self.getNodelist()

        if not MyBinaryTree.node_list: return []

        # root 为二叉树该层的父节点,i 为该层节点数量,_list 为输出列表
        def treeRecursion(root, i, _list):
            if root is None:
                return

            len1 = len(_list)
            if len1 <= i:  # 填充该层节点的占位元素
                for j in range(i - len1 + 1):
                    _list.append(None)

            _list[i] = root.val  # 填入该层的父节点元素
            treeRecursion(root.left, 2 * i, _list)  # 递归处理该层的左子树
            treeRecursion(root.right, 2 * i + 1, _list)  # 递归处理该层右子树

        _list = []
        treeRecursion(MyBinaryTree.node_list[0], 1, _list)  # 获得中间二叉树列表:[None, x1, x2, ...]
        while _list and _list[0] is None:  # 删除中间二叉树列表头部的空元素,得到:[x1, x2, ...]
            del (_list[0])
        return _list

    # 打印二叉树节点列表
    def printNodeList(self, node_list=[]):
        if not node_list:
            node_list = self.getNodelist()

        def getNodeName(node, name="Node"):
            return "None" if node is None or node.val is None else name + "{:0>2d}".format(node.val)

        print("node:".ljust(7), "val".ljust(5), "left".ljust(7), "right")  # 打印节点的字段名
        for node in range(len(node_list)):
            print(getNodeName(node_list[node]).ljust(6), end=": ")  # 打印节点的名称
            print((getNodeName(node_list[node], "") + ", ").ljust(6),
                  (getNodeName(node_list[node].left) + ", ").ljust(8),
                  getNodeName(node_list[node].right), sep='')  # 打印节点的 val、left、right


# 测试函数
def test_binarytree(list1):
    mytree = MyBinaryTree(list1)

    list2 = mytree.getListFromTree()
    print("原来的二叉树列表为:{}".format(list1))
    print("转换后二叉树列表为:{}".format(list2))
    print("转换前后的二叉树列表是否相等:{}".format(list1 == list2))
    print("二叉树的层列表为:{}".format(mytree.getLaylist()))

    print("\n二叉树节点列表为(完美对齐):")
    mytree.printNodeList(mytree.getNodelist())

    print("\n原来的列表转换为二叉树:{}".format(build(list1)))
    print("转换后的列表再转回二叉树:{}".format(build(list2)))


if __name__ == "__main__":
    list1 = [0, 1, 2, 3, 4, 5, 6, None, 7, None, 9, None, None, 10, ]  # 一般二叉树
    # list1 = [i for i in range(20)]  # 完全二叉树
    # list1 = [random.randint(0, 99) for i in range(20)]  # 完全二叉树
    test_binarytree(list1)

# S:\PythonProject\pyTest01\venv\Scripts\python.exe S:/PythonProject/pyTest01/main.py
# 原来的二叉树列表为:[0, 1, 2, 3, 4, 5, 6, None, 7, None, 9, None, None, 10]
# 转换后二叉树列表为:[0, 1, 2, 3, 4, 5, 6, None, 7, None, 9, None, None, 10]
# 转换前后的二叉树列表是否相等:True
# 二叉树的层列表为:[[0], [1, 2], [3, 4, 5, 6], [None, 7, None, 9, None, None, 10]]
#
# 二叉树节点列表为(完美对齐):
# node:   val   left    right
# Node00: 00,   Node01, Node02
# Node01: 01,   Node03, Node04
# Node02: 02,   Node05, Node06
# Node03: 03,   None,   Node07
# Node04: 04,   None,   Node09
# Node05: 05,   None,   None
# Node06: 06,   Node10, None
# None  : None, None,   None
# Node07: 07,   None,   None
# None  : None, None,   None
# Node09: 09,   None,   None
# None  : None, None,   None
# None  : None, None,   None
# Node10: 10,   None,   None
#
# 原来的列表转换为二叉树:
#       ____0__
#      /       \
#   __1         2___
#  /   \       /    \
# 3     4     5     _6
#  \     \         /
#   7     9       10
#
# 转换后的列表再转回二叉树:
#       ____0__
#      /       \
#   __1         2___
#  /   \       /    \
# 3     4     5     _6
#  \     \         /
#   7     9       10
#
#
# 进程已结束,退出代码0

  

posted on 2022-08-10 00:04  patton88  阅读(192)  评论(0编辑  收藏  举报

导航