你如何代表你的树?在我看来
l(_)
表示空树,并且
node(L,R)
表示一棵非空树。
而且我怀疑您height/2
有一个错误,因为您似乎已将空树的高度定义为 1(而不是 0)。
我可能会如下表示一棵二叉树:
nil
— 空树
tree(D,L,R)
— 一棵非空树,其中
这样可以代表树
a
/ \
b c
/ / \
d e f
作为
tree( a ,
tree( b ,
tree( d , nil , nil ) ,
nil
) ,
tree( c ,
tree( e , nil , nil ) ,
tree( f , nil , nil )
) .
叶节点(没有子树的树)看起来像
tree( data , nil , nil )
余额的确定
所以,从那个表示和定义开始工作
如果满足以下条件,则二叉树是平衡的:
- 它的左子树是平衡的
- 它的右子树是平衡的
- 子树各自的高度相差不超过1
我们可以很容易地为这个问题写一个描述性的解决方案:
is_balanced( nil ) . % the empty tree is balanced
is_balanced( tree(_,L,R) ) :- % a non-empty tree is balanced IF ...
is_balanced(L) , % - the left sub-tree is balanced
is_balanced(R) , % - the right sub-tree is balanced
tree_height(L,LH) , % - the height of the left sub-tree
tree_height(R,RH) , % - the height of the right sub-tree
abs( LH - RH ) < 2 % - differ by no more than 1
. % Right?
我们只需要计算一棵树的高度。
高度计算
可以如下计算这样一棵树的高度:
tree_height( nil , 0 ) . % the depth of an empty tree is zero.
tree_height( tree(_,L,R) , H ) :- % for a non-empty tree...
tree_height( L , LH ) , % - we compute the height of the left subtree
tree_height( R , RH ) , % - we compute the height of the right subtree
H is 1 + max( LH , RH ) % - the overall height is 1 more than the higher of the two values thus obtained.
. % Right?
效率
有人可能会注意到
- 似乎发生了很多树遍历,并且
is_balanced/2
与有可疑的相似之处tree_height/2
。
因此,可以通过将两者混合并即时计算深度来优化事物:
编辑:添加了包装谓词is_balanced/1
:
is_balanced( T ) :- is_balanced( T, _ ) .
is_balanced( nil , 0 ) . % the empty tree is balanced and has a height of zero.
is_balanced( tree(_,L,R) , H ) :- % a non-empty tree is balanced IF ...
is_balanced( L , LH ) , % - its left subtree is balanced, and
is_balanced( R , RH ) , % - its right subtree is balanced, and
abs( LH - RH) < 2 , % - their respective heights differ by no more than 1, and
H is 1 + max( LH , RH ) % - the current tree's height is 1 more than the larger of the heights of the two subtrees.
. % Easy! (And elegant!)