引入(Intro)
树由根节点的值和一系列的子树构成,并且这些子树也是树。在构造一棵树时,用列表list表示这些子树,列表中的元素也是一颗颗树。
构造器(Constructor)
用来构造一棵树
def tree(root_label, branches = []):
"""返回树的根节点值和一个列表元素为子树的列表
root_label: 根节点值
branches: 子树列表,初始为空
"""
for branch in branches:
# 遍历子树,每个子树都要是树
assert is_tree(branch), 'branches must be trees'
# 返回根节点+子树列表
return [root_label] + list(branches)
选择器(Selector)
用来定义构造器中的参数
def label(tree):
# 返回树的根节点,根节点索引为0
return tree[0]
def branches(tree):
# 返回子树,索引从1开始
return tree[1:]
def is_tree(tree):
# 输入一颗树,判断是不是树, 即树需要是列表,并且长度大于1
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)
树的递归演示
斐波拉契树
def fib_tree(n):
"""返回斐波拉契树的根节点值和一个列表元素为子树的列表
n: 根节点值
branches: 子树列表,初始为空
"""
if n == 0 or n == 1:
return tree(n)
else:
left, right = fib_tree(n - 2), fib_tree(n - 1)
# n号节点值为n-1号和n-2号之和
fib_n = label(left) + label(right)
return tree(fib_n, [left, right])
记录叶子节点个数
def count_leaves(tree):
# 是叶子节点就返回1
if is_leaf(tree):
return 1
else:
# 在每个子树里寻找叶子节点
branch_counts = [count_leaves(branch) for branch in branches(tree)]
# 把子树里的叶子节点加起来
return sum(branch_counts)
分割树
def partition_tree(n, m):
# 父节点值为0,树只有这一个节点,返回True
if n == 0:
return tree(True)
elif n < 0 or m == 0:
return tree(False)
else:
# 左节点值为n - m
left = partition_tree(n - m, m)
# 右节点值为m - 1 分割的n
right = partition_tree(n, m - 1)
return tree(m, [left, right])
def print_parts(tree, partition = []):
# 如果是叶子节点
if is_leaf(tree):
# 如果该节点值不为0
# 递归基本条件:在叶子节点前加 + 输出,
if label(tree):
print('+'.join(partition))
else:
left, right = branches(tree)
m = str(label(tree))
print_parts(left, partition + [m])
print_parts(right, partition)
二分树
def left_binarize(tree):
if is_leaf(tree):
return tree
if len(tree) > 2:
tree = [tree[1:],tree[0]]
return (left_binarize(branch) for branch in tree)
left_binarize([1,2,3,4,5,6,7])
找出树节点最大值
def tree_max(t):
"""Return the maximum label in a tree.
通过遍历子树,将所有节点存放在一个列表
"""
labels = [label(t)] + [label(b) for b in branches(t)]
return max(labels)
树的高度
最深叶子节点的深度
def height(t):
"""Return the height of a tree.
>>> t = tree(3, [tree(5, [tree(1)]), tree(2)])
>>> height(t)
2
"""
#若是叶子节点,高度为0
if is_leaf(t):
return 0
#若所有子树均为叶子节点,高度为1
if all([is_leaf(b) for b in branches(t)]):
return 1
else:
#找出所有子树的深度,返回最大就是树的高度
heights = [1 + height(b) for b in branches(t)]
return max(heights)
变化整棵树
将树的每个节点值平方,输出一棵新的树
def square_tree(t):
"""Return a tree with the square of every element in t"""
square = lambda x: x * x
label_s = square(label(t))
if is_leaf(t):
return tree(label_s)
else:
return tree(label_s, [square_tree(b) for b in branches(t)])
查找的路径
def find_path(tree,x):
"""返回一个列表,该列表元素值依次为到查找元素x的路径
tree: 被遍历的树
x: 要查找的元素
>>> t = tree(2, [tree(7, [tree(3), tree(6, [tree(5), tree(11)])] ), tree(15)])
>>> find_path(t, 5)
[2, 7, 6, 5]
>>> find_path(t, 10) # returns None
"""
# base case 如果只有一个节点,返回这个节点值的列表
if is_leaf(tree):
return [label(tree)]
# 遍历子树
for b in branches(tree):
path = find_path(b, x)
if path:
return [tree(label)] + path
输出深度为k的树
def prune(t, k):
"""returns a new tree that contains only the first k levels of the original tree"""
# base case
if k == 0:
return tree(label(t))
return ([label(t)] + prune(b, k - 1) for b in branches(t)])