Python与数据结构[3] -> 树/Tree[0] -> 二叉树及遍历二叉树的 Python 实现
二叉树 / Binary Tree
二叉树是树结构的一种,但二叉树的每一个节点都最多只能有两个子节点。
Binary Tree: 00 |_____ | | 00 00 |__ |__ | | | | 00 00 00 00
对于二叉树的遍历,主要有以下三种基本遍历方式:
- 先序遍历:先显示节点值,再显示左子树和右子树
- 中序遍历:先显示左子树,再显示节点值和右子树
- 后序遍历:先显示左子树和右子树,再显示节点值
下面将用代码构建一个二叉树,并实现三种遍历方式,
完整代码
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)
分段解释
首先定义树节点,包含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