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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# 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   patton88  阅读(230)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
历史上的今天:
2019-08-10 Radmin自动登录器 v3.0

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示