【Python】中順走査・後順走査の結果から二分木を構築するプログラムの書き方
二分木を構築する際、後順走査(ポストオーダートラバーサル)と中順走査(インオーダートラバーサル)の結果を入力として受け取るケースはよくあります。本記事では、ルート要素の設定や各種走査を行うメソッドを持つクラスを定義し、そのインスタンスを使って二分木を構築する方法を解説します。
以下に実際のサンプルコードを示します。
サンプルコード
class BinaryTree_struct:
def __init__(self, key=None):
self.key = key
self.left = None
self.right = None
def set_root(self, key):
self.key = key
def inorder_traversal(self):
if self.left is not None:
self.left.inorder_traversal()
print(self.key, end=' ')
if self.right is not None:
self.right.inorder_traversal()
def post_order_traversal(self):
if self.left is not None:
self.left.post_order_traversal()
if self.right is not None:
self.right.post_order_traversal()
print(self.key, end=' ')
def construct_btree(post_ord, in_ord):
if post_ord == [] or in_ord == []:
return None
key = post_ord[-1]
node = BinaryTree_struct(key)
index = in_ord.index(key)
node.left = construct_btree(post_ord[:index], in_ord[:index])
node.right = construct_btree(post_ord[index:-1], in_ord[index + 1:])
return node
post_ord = input('The input for post-order traversal is : ').split()
post_ord = [int(x) for x in post_ord]
in_ord = input('The input for in-order traversal is : ').split()
in_ord = [int(x) for x in in_ord]
my_instance = construct_btree(post_ord, in_ord)
print('Binary tree has been constructed...')
print('Verification in process..')
print('Post-order traversal is... ', end='')
my_instance.post_order_traversal()
print()
print('In-order traversal is... ', end='')
my_instance.inorder_traversal()
print()
実行結果
The input for post-order traversal is : 1 2 3 4 5 The input for in-order traversal is : 5 4 3 2 1 Binary tree has been constructed... Verification in process.. Post-order traversal is... 1 2 3 4 5 In-order traversal is... 5 4 3 2 1
コードの解説
必要な属性を持つ「BinaryTree_struct」クラスを作成します。
__init__メソッドでは、左ノードと右ノードを「None」で初期化します。
set_rootメソッドは、二分木のルートを設定するために使用します。
inorder_traversalメソッドは、「左 → ノード → 右」の順で走査を行う中順走査を実装しています。
post_order_traversalメソッドは、「左 → 右 → ノード」の順で走査を行う後順走査を実装しています。
construct_btree関数は、指定された走査結果をもとに二分木を再帰的に構築します。
ユーザーからの入力を受け取り、split()で分割した上で整数のリストに変換します。
construct_btree関数を呼び出して二分木を構築し、その結果を変数に格納します。
構築された木に対して後順走査と中順走査を実行し、正しく復元できたかどうかを検証します。
結果がコンソールに出力されます。
木の構築ロジックのポイント
このアルゴリズムの鍵となるのは、後順走査の最後の要素が必ず根(ルート)になるという二分木の性質です。construct_btree関数では、まず後順走査リストの末尾の要素をキーとして取得し、それが中順走査リストのどこにあるかを index() で特定します。中順走査は「左 → ノード → 右」の順で訪問するため、その位置より左側の要素が左部分木、右側の要素が右部分木に対応します。この処理を再帰的に繰り返すことで、元の二分木を完全に復元できる仕組みです。
-
Pythonで二分木の中間順トラバーサル(Inorder Traversal)を再帰なしで実装する方法
二分木(バイナリツリー)が与えられたとき、再帰を使わずに中間順トラバーサル(Inorder Traversal)で木を走査する方法を解説します。例えば、次のような二分木があるとします。この木に対して中間順トラバーサルを行うと、結果は [2,5,7,10,15,20] のようになります。中間順トラバーサルは「左の子 → 親ノード → 右の子」の順にノードを訪問するため、二分探索木の場合は値が昇順に出力されるという特徴があります。アルゴリズムの考え方再帰を使わずにスタックを活用することで、この問題を解決できます。手順は以下のとおりです。結果を格納する配列 res と、ノードを一時的に保持するスタッ
-
Pythonで二分木の直径を求める方法【DFSを使った実装解説】
二分木の直径とは二分木が与えられたとき、その木の直径(diameter)を計算することを考えます。二分木の直径とは、木の中の任意の2つのノードをつなぐ最長経路の長さのことです。重要なポイントとして、この経路は必ずしも根(ルート)を通るとは限りません。例えば、次のような木を考えてみましょう。この場合、経路 [4, 2, 1, 3] または [5, 2, 1, 3] の長さが3本の辺で構成されているため、直径は3となります。解法のアプローチこの問題はDFS(深さ優先探索)を使うことで効率的に解くことができます。手順は以下の通りです。DFSで各ノードを訪問しながら直径を求めます。まず答えを格納する変