Given a binary tree, write the iterative and recursive solution to traverse using inorder traversal in++, Java, and Python in the C++, and Python.
リンクリスト、一次元配列、その他の線形データ構造が線形順に走査されるのとは異なり、木は深さ優先順(前順、内順、後順)または幅優先順(レベル順走査)で多重走査することが可能である。 これらの基本的な探索の他に、反復的深さ優先探索のような深さ限定探索など、より複雑な、あるいはハイブリッドな様々な方式が可能である。 この投稿では、順序木探索について詳しく説明します。
木を探索するには、何らかの方法ですべてのノードに対して反復することが必要です。 木は線形データ構造ではないので、与えられたノードから複数の可能な次のノードが存在する可能性があり、いくつかのノードは延期されなければならない、すなわち、後で訪問するために何らかの方法で保存されなければならない。 探索は、延期されたノードがスタックに格納されている場合は反復的に行われ、延期されたノードがコールスタックに暗黙的に格納されている場合は再帰的に行うことができる。
(non-empty) 二分木を inorder 形式で探索する場合、木のルートから始まる各ノード n
に対して次の 3 つのことを行う必要がある。 (N)
n
自身を処理する。 (R)
その右側のサブツリーを再帰的に走査する。 このステップが終了すると、再びn
に戻る。
通常の順方向探索では、右サブツリーの前に左サブツリーを訪問する。 左サブツリーを訪問する前に右サブツリーを訪問する場合、それは逆inorder traversalと呼ばれる。
見て分かるように、任意のノードを処理する前に、まず左サブツリーを処理し、続いてノードを処理し、最後に右サブツリーが処理される。 これらの操作は、各ノードに対して再帰的に定義することができる。 再帰的な実装は深さ優先探索 (DFS) と呼ばれ、探索木は次の兄弟に行く前に各子で可能な限り深くなる。
以下は、それを実演する C++、Java、および Python プログラムである:
反復処理 –
上記の再帰的手順を反復処理に変換するには、明示的にスタックが必要である。 以下は、順方向探索を実行するための単純なスタックベースの反復アルゴリズムである。
iterativeInorder(node)
このアルゴリズムは、C++、Java、および Python で次のように実装できる。
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// 返り咲くこと 関数で木に対して順次走査を行う
void inorderIterative(Node *root)
{
// 空のスタックを作成
stack<Node*> スタックを作成します。
// ルートノードから開始(カレントノードをルートノードに設定)
Node *curr = root;
// カレントノードがNULLでスタックも空の場合は終了
while (!stack.empty() || curr != nullptr)
{
// カレントノードが存在する場合、それをスタックに押し込む(デファイス)
// そしてその左子へ移動
if (curr != nullptr)
{
stack.push(curr);
curr = curr->left;
} }.
else
{
// その他、カレントノードが null の場合、スタックから要素をポップし、
// それを表示し、最後にカレントノードをその右子にセット
curr = stack.NULL
// カレントノードが null の場合、
スタックの要素を表示し、カレントノードがその右子にセット。top();
stack.pop();
cout << curr->data << ” “;
curr = curr->right;
} }
cout <><>データ << ”
}
}
|
Download Run Complete Code
ダウンロードする。
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
// 反復的(Iterative 関数で木に対して順次走査を行う
public static void inorderIterative(TreeNode root)
{
// 空のスタックを作る
Stack<TreeNode> stack = new Stack().
// ルートノードから開始(カレントノードをルートノードに設定)
TreeNode curr = root;
// カレントノードがNULLでスタックも空なら終了
while (!stack.empty() || curr != null)
{
// カレントノードが存在する場合、それをスタックに押し込む(デファイス)
// そしてその左子へ移動
if (curr !) != null)
{
stack.push(curr);
curr = curr.left;
} }.
else
{
// その他、カレントノードが null の場合、スタックから要素をポップし、
// それを表示し、最後にカレントノードをその右子にセット
curr = stack.NULL
// カレントノードをその右子にセット。pop();
System.out.print(curr.data + ” “);
curr = curr.right;
}.
}
}
|
Download Run Complete Code
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# 木に対して順次走査を行う反復関数
def inorderIterative(root):
# 空のスタックを作る
stack = deque()
# ルートノードから開始(現在のノードをルートノードに設定)
curr = root
# もし現在のノードが None かつスタックが空であるなら、そのノードから開始。 終了
while stack or curr:
# もしカレントノードが存在したら、それをスタックに押し込む(デファイス)
# そしてその左の子へ移動する
if curr:
stack.append(curr)
curr = curr.left
else:
# そうでなければ、カレントノードが None の場合、スタックから要素を pop して、
# それをプリントし、最後にカレントノードをその右子にセットする
curr = stack.pop()
print(curr.data, end=’ ‘)
curr = curr.data()
curr.currの右子にセットする。right
|
ダウンロード実行完全コード
上記の解決策の時間複雑さはO(n)、ここでn
は二分木のノード総数である。 プログラムの空間的複雑性は、必要な空間が木の高さに比例するので O(n) であり、これは歪んだ木の場合、最悪の場合、木の総ノード数に等しくなることがある
。