Pythonで二分木の中間順トラバーサル(Inorder Traversal)を再帰なしで実装する方法
二分木(バイナリツリー)が与えられたとき、再帰を使わずに中間順トラバーサル(Inorder Traversal)で木を走査する方法を解説します。
例えば、次のような二分木があるとします。

この木に対して中間順トラバーサルを行うと、結果は [2,5,7,10,15,20] のようになります。中間順トラバーサルは「左の子 → 親ノード → 右の子」の順にノードを訪問するため、二分探索木の場合は値が昇順に出力されるという特徴があります。
アルゴリズムの考え方
再帰を使わずにスタックを活用することで、この問題を解決できます。手順は以下のとおりです。
- 結果を格納する配列
resと、ノードを一時的に保持するスタックstackを用意し、currをルートノードに設定する - 無限ループを実行する
currが null でない間、以下を繰り返すcurrをスタックにプッシュし、currを左の子ノードに更新する
- スタックの長さが 0 になったら、
resを返して終了する - スタックから要素をポップし、そのノードの値を
resに挿入する currを右の子ノードに更新する
このアプローチでは、まず左側のノードをすべてスタックに積み、最も深い左端のノードから順に処理していくことで、再帰と同じ動作を模倣しています。
実装例
以下のコードで実際の動作を確認してみましょう。
class TreeNode:
def __init__(self, data, left = None, right = None):
self.data = data
self.left = left
self.right = right
def insert(temp, data):
que = []
que.append(temp)
while (len(que)):
temp = que[0]
que.pop(0)
if (not temp.left):
temp.left = TreeNode(data)
break
else:
que.append(temp.left)
if (not temp.right):
temp.right = TreeNode(data)
break
else:
que.append(temp.right)
def make_tree(elements):
Tree = TreeNode(elements[0])
for element in elements[1:]:
insert(Tree, element)
return Tree
class Solution(object):
def inorderTraversal(self, root):
res, stack = [], []
current = root
while True:
while current:
stack.append(current)
current = current.left
if len(stack) == 0:
return res
node = stack[-1]
stack.pop(len(stack)-1)
if node.data != None:
res.append(node.data)
current = node.right
return res
ob1 = Solution()
root = make_tree([10,5,15,2,7,None,20])
print(ob1.inorderTraversal(root))入力
[10,5,15,2,7,null,20]
出力
[2,5,7,10,15,20]
コードのポイント
この実装における重要なポイントを整理します。
- 時間計算量: 各ノードを一度だけ訪問するため、O(n) です(n はノード数)。
- 空間計算量: スタックに最大で木の高さ分のノードが格納されるため、最悪ケースで O(n) となります。
- null ノードの扱い: 完全二分木を作成する過程で
Noneのノードが含まれるため、値が null のノードは結果に追加しないようにチェックしています。
再帰版と比較するとコードはやや複雑になりますが、深さが非常に大きい木を扱う場合には、Python の再帰呼び出し上限(デフォルトで約1000回)を回避できるため、この反復的な手法が有効です。
-
Pythonで二分木を反転する方法:再帰を使った実装を解説
二分木の反転とは二分木が与えられたとき、その左右の子ノードを入れ替えて「鏡像」のような木を作ることを二分木の反転(Invert Binary Tree)と呼びます。これはアルゴリズムの学習やコーディング面接でも頻出のトピックです。例えば、次のような二分木があったとします。これを反転すると、すべてのノードの左部分木と右部分木が入れ替わり、以下のような木になります。解き方:再帰的アプローチこの問題は再帰を使うと非常にシンプルに解けます。考え方は以下の3ステップです。ルートが None(null)であれば、そのまま返す(ベースケース)現在のノードの左ポインタと右ポインタを入れ替える左部分木と右部分木
-
Pythonで二分木の最大深度を求める方法|再帰を使った実装例を解説
Pythonで二分木の最大深度を求める二分木が与えられたとき、その最大深度を求める問題を考えます。木の最大深度とは、根(ルート)から葉ノードまでの最も長い経路をたどったときに通過するノード数のことです。例えば、下図のような二分木の場合、最大深度は 3 となります。解法のアプローチこの問題は再帰を使うことで、非常にシンプルに解くことができます。手順は以下のとおりです。再帰用のヘルパーメソッド solve(root, depth=0) を定義します。root が空(None)の場合は、そこまでの深さ depth をそのまま返します。それ以外の場合は、左部分木に対する solve(left, dep