一、树的基本概念
节点、边、根节点、叶子节点、分支节点、子树
二、基本术语
1.节点之间的关系:父节点、子节点、祖先节点、子孙节点、兄弟节点、堂兄弟节点,节点之间的路径--只能从上往下,路径长度--路径上经过多少条边
2.节点、树的属性:节点的深度、节点的高度、树的深度、节点的度、树的度(节点度的最大值)
3.有序树和无序树:逻辑上看,各子树是否有序,位置是否可以互换
4.森林:由m个互不相交的树组成森林
5.节点的权:有某种现实含义的数值(如:表示节点的重要性等)
6.节点的带权路径长度:从树的根到该节点的路径长度(经过的边数)与该节点上权值的乘积
7.树的带权路径长度:树中所有叶节点的带权路径长度之和
三、二叉树的基本概念
1.二叉树是n个节点的有限集合
2.空二叉树,n=0
3.由一个根节点和两个互不相交的被称为根的左子树和右子树组成,左子树和右子树又分别是一颗二叉树
4.每个节点最多只有两棵子树
5.左右子树不能颠倒
四、几个特殊二叉树
1.满二叉树, 只有最后一层有叶子节点,不存在度为1的节点
2.完全二叉树,每层的节点与满二叉树一一对应,满二叉树是一种完全二叉树
3.二叉排序树,左子树上节点的编号均小于根节点编号,右子树上所有节点关键字均大于根节点,左右子树又各是一棵二叉排序树,常用于搜索
4.平衡二叉树,左子树和右子树的深度之差不超过1
5.哈夫曼树:带权路径最短的二叉树称为哈弗曼树或最优二叉树
6.B树:一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多余两个子树
五、哈夫曼树的构造
1.权值最小的先组合,新节点的权值为左右子树的权值之和
2.组合的新二叉树的根节点与另外最小权值的节点组合
3.如果有两个节点均小于第一个二叉树的跟节点,就让那两个节点先结合
六、二叉树遍历
1.先序遍历(深度优先遍历)
先根、再左、再右,即ABCDEFGHK
2.中序遍历(深度优先遍历)
先左、再根、再右,即BDCAEHGKF
3.后序遍历(深度优先遍历)
先左、再右、再根,即DCBHKGFEA
4.层次遍历(广度优先遍历)
从上到下,从左到右进行遍历
七、代码实现
# 二叉树的链式存储
# 二叉树的节点类
class TreeNode:
def __init__(self, val=None, left=None, right=None):
self.val = val # 树节点存储的值
self.left = left # 左子树
self.right = right # 右子树
# 二叉树类
class BinaryTree:
def __init__(self):
self.root = None # 根节点初始化为None
self.addr_list = [] # 节点地址
def add(self, data):
node = TreeNode(data) # 实例化树节点
if self.root is None: # 如果根节点为空,则添加根节点,将地址存入addr中
self.root = node
self.addr_list.append(self.root)
else:
root_node = self.addr_list[0] # 将第一个元素设为根节点
if root_node.left is None: # 添加左孩子
root_node.left = node
self.addr_list.append(root_node.left)
elif root_node.right is None: # 添加右孩子
root_node.right = node
self.addr_list.append(root_node.right)
self.addr_list.pop(0) # 添加完右孩子之后,下一轮要添加的节点,是以根节点下面一个节点为根节点,所以需要删除掉第一个根节点
# 先序
def pre_traverse(self, root):
if root is None:
return
print(root.val, end=" ")
self.pre_traverse(root.left)
self.pre_traverse(root.right)
# 中序
def mid_traverse(self, root):
if root is None:
return
self.mid_traverse(root.left)
print(root.val, end=" ")
self.mid_traverse(root.right)
# 后序
def back_traverse(self, root):
if root is None:
return
self.mid_traverse(root.left)
self.mid_traverse(root.right)
print(root.val, end=" ")
# 层次遍历
def level_traverse(self, root):
from collections import deque
queue = deque()
queue.append(root)
while len(queue) > 0:
node = queue.popleft()
print(node.val, end=' ')
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if __name__ == '__main__':
tree = BinaryTree()
for i in range(1, 11):
tree.add(i)
print("先序遍历:", end=" ")
tree.pre_traverse(tree.root)
print()
print("中序遍历:", end=" ")
tree.mid_traverse(tree.root)
print()
print("后序遍历:", end=" ")
tree.back_traverse(tree.root)
print()
print("层次遍历:", end=" ")
tree.level_traverse(tree.root)