Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现

二叉树 / Binary Tree


 

二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点。

Binary Tree:
        00
        |_____
        |     |
        00    00
        |__   |__
        |  |  |  |
        00 00 00 00

对于二叉树的遍历,主要有以下三种基本遍历方式:

  1. 先序遍历:先显示节点值,再显示左子树和右子树
  2. 中序遍历:先显示左子树,再显示节点值和右子树
  3. 后序遍历:先显示左子树和右子树,再显示节点值

下面将用代码构建一个二叉树,并实现三种遍历方式,

完整代码

  1 class TreeNode:
  2     def __init__(self, val=None, lef=None, rgt=None):
  3         self.value = val
  4         self.left = lef
  5         self.right = rgt
  6 
  7     def __str__(self):
  8         return str(self.value)
  9 
 10 
 11 class BinaryTree:
 12     """
 13     Binary Tree:
 14         00
 15         |_____
 16         |     |
 17         00    00
 18         |__   |__
 19         |  |  |  |
 20         00 00 00 00
 21     """
 22     def __init__(self, root=None):
 23         self._root = root
 24 
 25     def __str__(self):
 26         return '\n'.join(map(lambda x: x[1]*4*' '+str(x[0]), self.pre_traversal()))
 27 
 28     def pre_traversal(self, root=None):
 29         if not root:
 30             root = self._root
 31         x = []
 32         depth = -1
 33 
 34         def _traversal(node):
 35             nonlocal depth
 36             depth += 1
 37             x.append((node, depth))
 38             if node and node.left is not None:
 39                 _traversal(node.left)
 40             if node and node.right is not None:
 41                 _traversal(node.right)
 42             depth -= 1
 43             return x
 44         return _traversal(root)
 45 
 46     def in_traversal(self, root=None):
 47         if not root:
 48             root = self._root
 49         x = []
 50         depth = -1
 51 
 52         def _traversal(node):
 53             nonlocal depth
 54             depth += 1
 55             if node and node.left is not None:
 56                 _traversal(node.left)
 57             x.append((node, depth))
 58             if node and node.right is not None:
 59                 _traversal(node.right)
 60             depth -= 1
 61             return x
 62         return _traversal(root)
 63 
 64     def post_traversal(self, root=None):
 65         if not root:
 66             root = self._root
 67         x = []
 68         depth = -1
 69 
 70         def _traversal(node):
 71             nonlocal depth
 72             depth += 1
 73             if node and node.left is not None:
 74                 _traversal(node.left)
 75             if node and node.right is not None:
 76                 _traversal(node.right)
 77             x.append((node, depth))
 78             depth -= 1
 79             return x
 80         return _traversal(root)
 81 
 82     @property
 83     def max_depth(self):
 84         return sorted(self.pre_traversal(), key=lambda x: x[1])[-1][1]
 85 
 86     def show(self, tl=None):
 87         if not tl:
 88             tl = self.pre_traversal()
 89         print('\n'.join(map(lambda x: x[1]*4*' '+str(x[0]), tl)))
 90 
 91     def make_empty(self):
 92         self.__init__()
 93 
 94     def insert(self, item):
 95         if self._root is None:
 96             self._root = TreeNode(item)
 97             return
 98 
 99         def _insert(item, node):
100             if not node:
101                 return TreeNode(item)
102             if node.left is None:
103                 node.left = _insert(item, node.left)
104             elif node.right is None:
105                 node.right = _insert(item, node.right)
106             else: 
107                 if len(self.pre_traversal(node.left)) <= len(self.pre_traversal(node.right)):
108                     node.left = _insert(item, node.left)
109                 else:
110                     node.right = _insert(item, node.right)
111             return node
112         self._root = _insert(item, self._root)
113 
114 
115 if __name__ == '__main__':
116     bt = BinaryTree()
117     print('\nBinary Tree:')
118     '''
119     0
120     |_____
121     |     |
122     1     2
123     |__   |__
124     |  |  |  |
125     3  5  4  6 
126     '''
127     for i in range(7):
128         bt.insert(i)
129     bt.show()
130     print('\n------Pre-traversal-------')
131     print(bt)
132 
133     print('\n------Post-traversal------')
134     bt.show(bt.post_traversal())
135     print('\n-------In-traversal-------')
136     bt.show(bt.in_traversal()) 
137 
138     bt.make_empty()
139     print('\n-------Empty-tree-------')
140     print(bt)
View Code

分段解释

首先定义树节点,包含3个属性(指针引用),分别为:当前值,左子树节点,右子树节点

1 class TreeNode:
2     def __init__(self, val=None, lef=None, rgt=None):
3         self.value = val
4         self.left = lef
5         self.right = rgt
6 
7     def __str__(self):
8         return str(self.value)

构建一个二叉树类,构造函数中包含一个根节点属性,

 1 class BinaryTree:
 2     """
 3     Binary Tree:
 4         00
 5         |_____
 6         |     |
 7         00    00
 8         |__   |__
 9         |  |  |  |
10         00 00 00 00
11     """
12     def __init__(self, root=None):
13         self._root = root

重定义__str__方法,在打印树时,依据树的深度添加tab显示,类似于文件目录(文件分级目录原本便是由树实现的)的显示方式

1     def __str__(self):
2         return '\n'.join(map(lambda x: x[1]*4*' '+str(x[0]), self.pre_traversal()))

定义先序遍历方法,通过递归的方式进行实现,优先显示当前节点

 1     def pre_traversal(self, root=None):
 2         if not root:
 3             root = self._root
 4         x = []
 5         depth = -1
 6 
 7         def _traversal(node):
 8             nonlocal depth
 9             depth += 1
10             x.append((node, depth))
11             if node and node.left is not None:
12                 _traversal(node.left)
13             if node and node.right is not None:
14                 _traversal(node.right)
15             depth -= 1
16             return x
17         return _traversal(root)

定义中序遍历方法,与先序遍历基本相同,只是处理当前节点的顺序在左子树之后,右子树之前,

 1     def in_traversal(self, root=None):
 2         if not root:
 3             root = self._root
 4         x = []
 5         depth = -1
 6 
 7         def _traversal(node):
 8             nonlocal depth
 9             depth += 1
10             if node and node.left is not None:
11                 _traversal(node.left)
12             x.append((node, depth))
13             if node and node.right is not None:
14                 _traversal(node.right)
15             depth -= 1
16             return x
17         return _traversal(root)

定义后序遍历方法,处理当前节点的顺序在左子树和右子树之后,

 1     def post_traversal(self, root=None):
 2         if not root:
 3             root = self._root
 4         x = []
 5         depth = -1
 6 
 7         def _traversal(node):
 8             nonlocal depth
 9             depth += 1
10             if node and node.left is not None:
11                 _traversal(node.left)
12             if node and node.right is not None:
13                 _traversal(node.right)
14             x.append((node, depth))
15             depth -= 1
16             return x
17         return _traversal(root)

再定义一些树的基本方法,显示树的时候,优先采用先序遍历显示,

 1     @property
 2     def max_depth(self):
 3         return sorted(self.pre_traversal(), key=lambda x: x[1])[-1][1]
 4 
 5     def show(self, tl=None):
 6         if not tl:
 7             tl = self.pre_traversal()
 8         print('\n'.join(map(lambda x: x[1]*4*' '+str(x[0]), tl)))
 9 
10     def make_empty(self):
11         self.__init__()

最后定义二叉树的插入方法,插入方式尽量保证二叉树的平衡,插入顺序为当前节点->左->右,当左右节点都不为空时,则递归插入左子树和右子树中,深度较小的那一棵树。

 1     def insert(self, item):
 2         if self._root is None:
 3             self._root = TreeNode(item)
 4             return
 5 
 6         def _insert(item, node):
 7             if not node:
 8                 return TreeNode(item)
 9             if node.left is None:
10                 node.left = _insert(item, node.left)
11             elif node.right is None:
12                 node.right = _insert(item, node.right)
13             else: 
14                 if len(self.pre_traversal(node.left)) <= len(self.pre_traversal(node.right)):
15                     node.left = _insert(item, node.left)
16                 else:
17                     node.right = _insert(item, node.right)
18             return node
19         self._root = _insert(item, self._root)

定义完二叉树类后,对二叉树进行构建,插入元素并利用三种遍历方式显示二叉树。

 1 if __name__ == '__main__':
 2     bt = BinaryTree()
 3     print('\nBinary Tree:')
 4     '''
 5     0
 6     |_____
 7     |     |
 8     1     2
 9     |__   |__
10     |  |  |  |
11     3  5  4  6 
12     '''
13     for i in range(7):
14         bt.insert(i)
15     bt.show()
16     print('\n------Pre-traversal-------')
17     print(bt)
18 
19     print('\n------Post-traversal------')
20     bt.show(bt.post_traversal())
21     print('\n-------In-traversal-------')
22     bt.show(bt.in_traversal()) 
23 
24     bt.make_empty()
25     print('\n-------Empty-tree-------')
26     print(bt)

三种遍历方式显示结果如下

Binary Tree:
0
    1
        3
        5
    2
        4
        6

------Pre-traversal-------
0
    1
        3
        5
    2
        4
        6

------Post-traversal------
        3
        5
    1
        4
        6
    2
0

-------In-traversal-------
        3
    1
        5
0
        4
    2
        6

-------Empty-tree-------
None

 

posted @ 2018-01-14 22:41  StackLike  阅读(1374)  评论(0编辑  收藏  举报