Pythonで二分木の葉ノードを新しいルートに変更するプログラムの実装方法
二分木と、その葉(リーフ)に位置する1つのノードが与えられたとしましょう。ここでの課題は、その葉ノードを二分木の新しいルート(根)ノードへと変更することです。この操作は、次の2つのルールに従って行います。
- 左の子の移動: ノードに左の子が存在する場合、その子は右側へ移動します。
- 親の移動: ノードの親は、そのノードの左の子になります。この処理の過程で、元の親ノードからそのノードへのリンクは切断(null)されるため、親ノードは子を1つだけ持つ状態になります。
今回扱うツリーのノード構造は以下の通りです。
TreeNode:
data: <整数>
left: <TreeNodeへのポインタ>
right: <TreeNodeへのポインタ>
parent: <TreeNodeへのポインタ>
処理の結果として、変換後のツリーのルートを返す必要があります。
具体例
例えば、次のような二分木が与えられたとします。

ここで新しいルートを「8」に変更すると、変換後のツリーの中間順(inorder)走査の結果は次のようになります。
2, 3, 4, 5, 7, 6, 8,
ご覧の通り、新しいツリーのルートノードは8となっています。
解決アプローチ
この問題を解くために、再帰的なヘルパー関数 helper() を定義し、以下の手順で処理を進めます。
- helper(node, new_par) 関数を定義する。
- node が root と一致する場合:
- node の親を new_par に設定する。
- node の左の子が new_par と一致する場合は、左の子を null にする。
- node の右の子が new_par と一致する場合は、右の子を null にする。
- root を返す。
- node の左の子が null でない場合、node の右の子を現在の左の子に置き換える。
- node の親の左の子が node と一致する場合、親の左の子を null にする。
- node の左の子を helper(node の親, node) の戻り値に設定する。
- node の親を new_par に更新する。
- node を返す。
- node が root と一致する場合:
- helper(leaf, None) を呼び出した結果を返す。
それでは、実際の実装例を見ながら理解を深めていきましょう。
実装例(Python)
import collections
class TreeNode:
def __init__(self, data, left = None, right = None, parent = None):
self.data = data
self.left = left
self.right = right
self.parent = parent
def insert(temp,data):
que = []
que.append(temp)
while (len(que)):
temp = que[0]
que.pop(0)
if (not temp.left):
if data is not None:
temp.left = TreeNode(data, parent = temp)
else:
temp.left = TreeNode(0, parent = temp)
break
else:
que.append(temp.left)
if (not temp.right):
if data is not None:
temp.right = TreeNode(data, parent = temp)
else:
temp.right = TreeNode(0, parent = temp)
break
else:
que.append(temp.right)
def make_tree(elements):
Tree = TreeNode(elements[0])
for element in elements[1:]:
insert(Tree, element)
return Tree
def search_node(root, element):
if (root == None):
return None
if (root.data == element):
return root
res1 = search_node(root.left, element)
if res1:
return res1
res2 = search_node(root.right, element)
return res2
def print_tree(root):
if root is not None:
print_tree(root.left)
print(root.data, end = ', ')
print_tree(root.right)
def solve(root, leaf):
def helper(node, new_par):
if node == root:
node.parent = new_par
if node.left == new_par:
node.left = None
if node.right == new_par:
node.right = None
return root
if node.left:
node.right = node.left
if node.parent.left == node:
node.parent.left = None
node.left = helper(node.parent, node)
node.parent = new_par
return node
return helper(leaf, None)
root = make_tree([5, 3, 7, 2, 4, 6, 8])
root = solve(root, search_node(root, 8))
print_tree(root)
入力
root = make_tree([5, 3, 7, 2, 4, 6, 8]) root = solve(root, search_node(root, 8))
出力
2, 3, 4, 5, 7, 6, 8,
-
Pythonで二分木の各レベルの最大幅を求めるプログラム
二分木が与えられたとき、ツリー内の任意のレベルにおける最大幅を求めることを考えます。ここでいう「レベルの幅」とは、そのレベルにおいて最も左端にあるノードと最も右端にあるノードの間に含まれるノード数のことです。例えば、次のような二分木が入力として与えられた場合を考えてみましょう。この場合、出力は 2 となります。解決のための手順この問題を解くために、以下の手順に従います。各深さにおける位置の最小値と最大値を保持するマップ d を作成します。初期値は、最小値を無限大(∞)、最大値を 0 とします。関数 dfs() を定義します。この関数は引数として root、pos := 0、depth := 0
-
Pythonで二分木を反転する方法:再帰を使った実装を解説
二分木の反転とは二分木が与えられたとき、その左右の子ノードを入れ替えて「鏡像」のような木を作ることを二分木の反転(Invert Binary Tree)と呼びます。これはアルゴリズムの学習やコーディング面接でも頻出のトピックです。例えば、次のような二分木があったとします。これを反転すると、すべてのノードの左部分木と右部分木が入れ替わり、以下のような木になります。解き方:再帰的アプローチこの問題は再帰を使うと非常にシンプルに解けます。考え方は以下の3ステップです。ルートが None(null)であれば、そのまま返す(ベースケース)現在のノードの左ポインタと右ポインタを入れ替える左部分木と右部分木