树的基本概念
树是一种数据结构,它模拟了一种层次结构,其中每个元素称为节点。树的一个节点可以有零个或多个子节点,但每个节点只有一个父节点,除了根节点,它没有父节点。树的一个重要特性是它没有循环,即从一个节点出发,不能回到该节点。
树的基本组成部分包括:
- 根节点:树的起始节点,没有父节点。
- 分支:连接到根节点的子树。
- 叶子节点:没有子节点的节点。
- 节点:树中的任何元素。
树的数据抽象
在Python中,我们可以通过列表来表示树。树的数据抽象包括构造器和选择器:
def tree(root_label, branches=[]):
for branch in branches:
assert is_tree(branch), 'branches must be trees'
return [root_label] + list(branches)
def label(tree):
return tree[0]
def branches(tree):
return tree[1:]
def is_tree(tree):
if type(tree) != list or len(tree) < 1:
return False
for branch in branches(tree):
if not is_tree(branch):
return False
return True
def is_leaf(tree):
return not branches(tree)
树的构造和操作示例
我们可以通过嵌套表达式来构造树。例如,下面的树t
有一个根标签3和两个分支:
t = tree(3, [tree(1), tree(2, [tree(1), tree(1)])])
print(t) # [3, [1], [2, [1], [1]]]
print(label(t)) # 3
print(branches(t)) # [[1], [2, [1], [1]]]
print(label(branches(t)[1])) # 2
print(is_leaf(t)) # False
print(is_leaf(branches(t)[0])) # True
树递归函数
树递归函数可以用来构造和处理树。例如,Fibonacci树递归地构造了一个Fibonacci数列的树结构:
def fib_tree(n):
if n == 0 or n == 1:
return tree(n)
else:
left, right = fib_tree(n-2), fib_tree(n-1)
fib_n = label(left) + label(right)
return tree(fib_n, [left, right])
print(fib_tree(5)) # [5, [2, [1], [1, [0], [1]]], [3, [1, [0], [1]], [2, [1], [1, [0], [1]]]]]
树的叶子计数
我们可以使用递归函数来计算树的叶子节点数量:
def count_leaves(tree):
if is_leaf(tree):
return 1
else:
branch_counts = [count_leaves(b) for b in branches(tree)]
return sum(branch_counts)
print(count_leaves(fib_tree(5))) # 8
分区树
分区树表示一个整数的分区。分区树的构造和打印如下:
def partition_tree(n, m):
if n == 0:
return tree(True)
elif n < 0 or m == 0:
return tree(False)
else:
left = partition_tree(n-m, m)
right = partition_tree(n, m-1)
return tree(m, [left, right])
def print_parts(tree, partition=[]):
if is_leaf(tree):
if label(tree):
print(' + '.join(partition))
else:
left, right = branches(tree)
m = str(label(tree))
print_parts(left, partition + [m])
print_parts(right, partition)
print_parts(partition_tree(6, 4))
二叉化树
二叉化树是将一个树转换为右分支的二叉树:
def right_binarize(tree):
if is_leaf(tree):
return tree
if len(tree) > 2:
tree = [tree[0], tree[1:]]
return [right_binarize(b) for b in tree]
print(right_binarize([1, 2, 3, 4, 5, 6, 7])) # [1, [2, [3, [4, [5, [6, 7]]]]]]
课后练习
- 构造一个树:构造一个树,根节点为5,有两个分支,第一个分支是叶子节点3,第二个分支是根节点为4的树,该树有两个叶子节点2和1。
- 计算叶子节点数量:编写一个函数
count_nodes
,计算树中所有节点的数量。 - 打印树结构:编写一个函数
print_tree
,以缩进格式打印树的结构。 - 树的深度:编写一个函数
tree_depth
,计算树的最大深度。
课后练习答案
- 构造一个树:
t = tree(5, [tree(3), tree(4, [tree(2), tree(1)])])
print(t) # [5, [3], [4, [2], [1]]]
- 计算叶子节点数量:
def count_nodes(tree):
if is_leaf(tree):
return 1
else:
return 1 + sum(count_nodes(b) for b in branches(tree))
print(count_nodes(t)) # 5
- 打印树结构:
def print_tree(tree, indent=0):
print(' ' * indent + str(label(tree)))
for branch in branches(tree):
print_tree(branch, indent + 2)
print_tree(t)
- 树的深度:
def tree_depth(tree):
if is_leaf(tree):
return 1
else:
return 1 + max(tree_depth(b) for b in branches(tree))
print(tree_depth(t)) # 3