次のツリーはあなたの定義に当てはまりますが、私にはあまりバランスが取れていないようです。
編集この答えは間違っていますが、まだ削除したくないほど興味深いものが含まれています。アルゴリズムはバランスの取れたツリーを生成しますが、最小のツリーは生成しません。追加するノードの数は次のとおりです。
ここで、n
範囲はツリー内のすべてのノードにまたがり、lower(n)
はn
より低い深さupper(n)
の子の深さであり、はより高い深さのの子のn
深さです。k
最初のフィボナッチ数の合計がであるという事実を使用してfib(k+2)-1
、内部の合計を。に置き換えることができfib(upper(n)) - fib(lower(n) + 2)
ます。
式は(多かれ少なかれ)次のアルゴリズムから導出され、ツリーにノードを追加して、バランスを取ります(Pythonでは、関連するアルゴリズムのみを表示します)。
def balance(tree, label):
if tree is None:
return (None, 0)
left, left_height = balance(tree.left_child, label)
right, right_height = balance(tree.right_child, label)
while left_height < right_height - 1:
left = Node(label(), left, balanced_tree(left_height - 1, label))
left_height += 1
while right_height < left_height - 1:
right = Node(label(), right, balanced_tree(right_height - 1, label))
right_height += 1
return (Node(tree.label, left, right), max(left_height, right_height) + 1)
def balanced_tree(depth, label):
if depth <= 0:
return None
else:
return Node(label(),
balanced_tree(depth - 1, label),
balanced_tree(depth - 2, label))
要求に応じて:ツリーを作成する代わりにカウントを報告します。
def balance(tree):
if tree is None:
return (0, 0)
left, left_height = balance(tree.left_child)
right, right_height = balance(tree.right_child)
while left_height < right_height - 1:
left += balanced_tree(left_height - 1) + 1
left_height += 1
while right_height < left_height - 1:
right += balanced_tree(right_height - 1) + 1
right_height += 1
return (left + right, max(left_height, right_height) + 1)
def balanced_tree(depth):
if depth <= 0:
return 0
else:
return (1 + balanced_tree(depth - 1)
+ balanced_tree(depth - 2))
編集:実際には、深さnの最小バランスツリーのサイズをより効率的に計算する(つまり、メモ化するか、閉じた形式を使用する:それはただfibonacci(n+1)-1
)以外は、おそらくあなたが得ることができるのと同じくらい効率的だと思います。バランス状態をテストするためにツリー内のすべてのノードを調べます。そのアルゴリズムはすべてのノードを正確に1回調べます。