[2021 Spring] CS61A 学习笔记 Homework 4: Trees, Data Abstraction
作业地址: https://inst.eecs.berkeley.edu/~cs61a/sp21/hw/hw04/
Abstraction
Q1: Weights
参考mobile和arm同一模板
def planet(size):
"""Construct a planet of some size."""
assert size > 0
"*** YOUR CODE HERE ***"
return ['planet', size]
def size(w):
"""Select the size of a planet."""
assert is_planet(w), 'must call size on a planet'
"*** YOUR CODE HERE ***"
return w[1]
Q2: Balanced
要求使用abstraction barrier,禁止使用索引。
考虑平衡性:
- 当m是planet时,本身是平衡的,直接返回True;
- 当m是mobile时,需要计算arm的扭矩torque,torque = arm下的weight*length,左右两边的torque相等即表示该mobile是平衡的;
- 另一个要求是每个mobile下的arm都平衡,递归即可。
def balanced(m):
"""Return whether m is balanced.
>>> t, u, v = examples()
>>> balanced(t)
True
>>> balanced(v)
True
>>> w = mobile(arm(3, t), arm(2, u))
>>> balanced(w)
False
>>> balanced(mobile(arm(1, v), arm(1, w)))
False
>>> balanced(mobile(arm(1, w), arm(1, v)))
False
>>> from construct_check import check
>>> # checking for abstraction barrier violations by banning indexing
>>> check(HW_SOURCE_FILE, 'balanced', ['Index'])
True
"""
"*** YOUR CODE HERE ***"
if is_planet(m):
return True
return total_weight(end(left(m))) * length(left(m)) == \
total_weight(end(right(m))) * length(right(m)) and \
balanced(end(left(m))) and balanced(end(right(m)))
Q3: Totals
- planet返回叶节点,即tree(total_weight(m))
- mobile返回带有枝干的树节点,枝为end(arm)的totals_tree,即tree(total_weight(m), [totals_tree(end(left(m))), totals_tree(end(right(m)))])
def totals_tree(m):
"""Return a tree representing the mobile with its total weight at the root.
>>> t, u, v = examples()
>>> print_tree(totals_tree(t))
3
2
1
>>> print_tree(totals_tree(u))
6
1
5
3
2
>>> print_tree(totals_tree(v))
9
3
2
1
6
1
5
3
2
>>> from construct_check import check
>>> # checking for abstraction barrier violations by banning indexing
>>> check(HW_SOURCE_FILE, 'totals_tree', ['Index'])
True
"""
"*** YOUR CODE HERE ***"
if is_planet(m):
return tree(total_weight(m))
return tree(total_weight(m), [totals_tree(end(left(m))), totals_tree(end(right(m)))])
Trees
Q4: Replace Thor at Leaf
base:节点为叶节点且值为'thor'时替换为thors_replacement
def replace_thor_at_leaf(t, thors_replacement):
"""Returns a new tree where every leaf value equal to "thor" has
been replaced with thors_replacement.
>>> yggdrasil = tree('odin',
... [tree('balder',
... [tree('thor'),
... tree('freya')]),
... tree('frigg',
... [tree('thor')]),
... tree('thor',
... [tree('sif'),
... tree('thor')]),
... tree('thor')])
>>> laerad = copy_tree(yggdrasil) # copy yggdrasil for testing purposes
>>> print_tree(replace_thor_at_leaf(yggdrasil, 'freya'))
odin
balder
freya
freya
frigg
freya
thor
sif
freya
freya
>>> laerad == yggdrasil # Make sure original tree is unmodified
True
"""
"*** YOUR CODE HERE ***"
if is_leaf(t) and label(t) == 'thor':
return tree(thors_replacement)
return tree(label(t), [replace_thor_at_leaf(c, thors_replacement) for c in branches(t)])
Q5: Has Path
- label(t)与word[0]不相等时,返回False
- label(t)与word[0]相等,在len(word)等于1时,完全匹配,返回True
- for循环遍历branch,传入word[1:].
def has_path(t, word):
"""Return whether there is a path in a tree where the entries along the path
spell out a particular word.
>>> greetings = tree('h', [tree('i'),
... tree('e', [tree('l', [tree('l', [tree('o')])]),
... tree('y')])])
>>> print_tree(greetings)
h
i
e
l
l
o
y
>>> has_path(greetings, 'h')
True
>>> has_path(greetings, 'i')
False
>>> has_path(greetings, 'hi')
True
>>> has_path(greetings, 'hello')
True
>>> has_path(greetings, 'hey')
True
>>> has_path(greetings, 'bye')
False
>>> has_path(greetings, 'hint')
False
"""
assert len(word) > 0, 'no path for empty word.'
"*** YOUR CODE HERE ***"
if label(t) != word[0]:
return False
elif len(word) == 1:
return True
for b in branches(t):
if has_path(b, word[1:]):
return True
return False
Q6: Preorder
前序遍历:
- 叶节点返回[label(t)]
- 对于每个非叶节点b,将preorder(b)累加到res
- 返回根节点+res
def preorder(t):
"""Return a list of the entries in this tree in the order that they
would be visited by a preorder traversal (see problem description).
>>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])])
>>> preorder(numbers)
[1, 2, 3, 4, 5, 6, 7]
>>> preorder(tree(2, [tree(4, [tree(6)])]))
[2, 4, 6]
"""
"*** YOUR CODE HERE ***"
if is_leaf(t):
return [label(t)]
res = []
for b in branches(t):
res += preorder(b)
return [label(t)] + res