数据结构——1.1树
单纯记录,代码都是python
术语
- 根节点:无前驱(双亲)
- 节点的度:拥有的子树的个数
- 树的度:所有节点度的最大值
- 叶子节点/终端节点:度=0,没有后继(孩子)
- 分支节点/内部节点:其他的,度≠0
- 树的深度:最大的层次
- 前后层级:双亲和孩子
- 同一层级:同一个双亲-兄弟节点,不同双亲-堂兄弟节点
- 有序树,无序树
- 森林(一堆不相交的树),如果删除一棵树的根节点,所有子树构成森林,一棵树是特殊的森林
二叉树
每个节点最多两个子节点,所有树都可以和二叉树相互转换
- 子树有左右之分,不能颠倒,只有一个子树,则不用区分(显然)
第i层,最多有 2^(i-1) 个节点,至少有1 个节点
深度为k的二叉树,最多有2^k-1个节点,至少有k个节点
任何二叉树,叶子数为a,度为2的节点数为b,则a=b+1
满二叉树
所有内部节点都有两个子节点,即深度为k有2^k-1个节点
叶子节点全在最后一层
完全二叉树
定义:深度为k有n个节点,当且仅当某个节点都和深度为k的满二叉树中编号为1~n的节点一一对应
理解:从上至下,从左至右编号,完全二叉树是满二叉树移除最后一个,最后两个这样的二叉树,就是只能队伍最后一个或者连续几个没了,前面必须和满二叉树一样
- n个节点的完全二叉树深度为log2(n)取下整+1
- 父子节点编号关系
存储和遍历+代码
- 顺序存储:
按编号,没有的位置用0代替,浪费空间,适合满二叉树和完全二叉树
class ArrayBinaryTree:
def __init__(self, capacity):
# 初始化一个定长数组用于存储二叉树的节点,容量为capacity
self.tree = [None] * capacity
self.capacity = capacity
# 添加元素到树中
def add(self, value):
# 检查树是否满了
for i in range(self.capacity):
if self.tree[i] is None:
self.tree[i] = value
return
print("树已满,无法添加新元素")
# 访问指定位置的节点
def get(self, index):
if 0 <= index < self.capacity:
return self.tree[index]
else:
return None
# 获取左子节点
def get_left_child(self, index):
left_index = 2 * index + 1
if left_index < self.capacity:
return self.tree[left_index]
return None
# 获取右子节点
def get_right_child(self, index):
right_index = 2 * index + 2
if right_index < self.capacity:
return self.tree[right_index]
return None
# 获取父节点
def get_parent(self, index):
if index == 0:
return None # 根节点没有父节点
parent_index = (index - 1) // 2
return self.tree[parent_index]
# 展示整个树的数组表示
def display(self):
print(self.tree)
# 示例:构建一个容量为 7 的顺序存储二叉树
tree = ArrayBinaryTree(7)
# 添加元素(按顺序添加,模拟完全二叉树)
tree.add(1) # 根节点
tree.add(2) # 根的左子节点
tree.add(3) # 根的右子节点
tree.add(4) # 2的左子节点
tree.add(5) # 2的右子节点
tree.add(6) # 3的左子节点
tree.add(7) # 3的右子节点
# 打印整个二叉树数组表示
tree.display()
# 获取节点
print("索引 0 处的节点值:", tree.get(0)) # 根节点 1
print("索引 1 处的左子节点值:", tree.get_left_child(1)) # 4
print("索引 1 处的右子节点值:", tree.get_right_child(1)) # 5
print("索引 5 处的父节点值:", tree.get_parent(5)) # 3
- 链式存储
左子节点|数据|右子节点,
n个节点,有n+1个空指针域
一共2n个,每个节点一个父节点,n-个有存放,2n-n+1
- 三叉链表
- 左子节点|数据|父节点|右子节点,
class TreeNode:
def __init__(self, value):
self.value = value # 节点值
self.left = None # 左子节点
self.right = None # 右子节点
class BinaryTree:
def __init__(self):
self.root = None # 初始化根节点为空
# 插入元素,按照二叉树的规则插入(这里以二叉搜索树为例)
def insert(self, value):
new_node = TreeNode(value)
if self.root is None:
self.root = new_node # 如果根节点为空,直接插入为根节点
else:
self._insert_recursive(self.root, new_node)
# 递归插入节点
def _insert_recursive(self, current_node, new_node):
if new_node.value < current_node.value:
# 如果新节点的值小于当前节点,插入到左子树
if current_node.left is None:
current_node.left = new_node
else:
self._insert_recursive(current_node.left, new_node)
else:
# 如果新节点的值大于或等于当前节点,插入到右子树
if current_node.right is None:
current_node.right = new_node
else:
self._insert_recursive(current_node.right, new_node)
# 先序遍历 (根 -> 左 -> 右)
def preorder_traversal(self, node):
if node:
print(node.value, end=" ") # 访问根节点
self.preorder_traversal(node.left) # 递归访问左子树
self.preorder_traversal(node.right) # 递归访问右子树
# 中序遍历 (左 -> 根 -> 右)
def inorder_traversal(self, node):
if node:
self.inorder_traversal(node.left) # 递归访问左子树
print(node.value, end=" ") # 访问根节点
self.inorder_traversal(node.right) # 递归访问右子树
# 后序遍历 (左 -> 右 -> 根)
def postorder_traversal(self, node):
if node:
self.postorder_traversal(node.left) # 递归访问左子树
self.postorder_traversal(node.right) # 递归访问右子树
print(node.value, end=" ") # 访问根节点
# 示例:构建一棵二叉树
tree = BinaryTree()
# 插入节点
tree.insert(5)
tree.insert(3)
tree.insert(7)
tree.insert(2)
tree.insert(4)
tree.insert(6)
tree.insert(8)
# 遍历树结构
print("先序遍历:")
tree.preorder_traversal(tree.root) # 输出:5 3 2 4 7 6 8
print("\n中序遍历:")
tree.inorder_traversal(tree.root) # 输出:2 3 4 5 6 7 8
print("\n后序遍历:")
tree.postorder_traversal(tree.root) # 输出:2 4 3 6 8 7 5
如果所有节点的值都没有相同的,、前中后序列唯一
前+中,或者后+中可以确定唯一的二叉树
表达式计算的代码——后序遍历(Post-order Traversal):
3 + (5 * 2)
+
/ \
3 *
/ \
5 2
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
# 判断是否为运算符
def is_operator(c):
return c in ['+', '-', '*', '/']
# 递归计算表达式树的值
def evaluate_expression_tree(node):
if node is None:
return 0
# 如果当前节点是叶节点(操作数),直接返回其值
if node.left is None and node.right is None:
return int(node.value)
# 递归计算左子树和右子树的值
left_value = evaluate_expression_tree(node.left)
right_value = evaluate_expression_tree(node.right)
# 根据当前节点的运算符执行计算
if node.value == '+':
return left_value + right_value
elif node.value == '-':
return left_value - right_value
elif node.value == '*':
return left_value * right_value
elif node.value == '/':
return left_value / right_value
# 示例构建表达式树: 3 + (5 * 2)
root = TreeNode('+')
root.left = TreeNode('3')
root.right = TreeNode('*')
root.right.left = TreeNode('5')
root.right.right = TreeNode('2')
# 计算表达式的值
result = evaluate_expression_tree(root)
print(f"表达式的值为: {result}")