[解決済み] スタックや再帰を使わないMorrisの順次木探索について説明する。
質問
スタックや再帰を使用しない、以下のMorris inorder tree traversal アルゴリズムの理解を助けてくれる人はいますか?私はそれがどのように動作するかを理解しようとしたが、それはちょうど私をエスケープされています。
1. Initialize current as root
2. While current is not NULL
If current does not have left child
a. Print current’s data
b. Go to the right, i.e., current = current->right
Else
a. In current's left subtree, make current the right child of the rightmost node
b. Go to this left child, i.e., current = current->left
という形でツリーが修正されるそうですね。
current node
にすることで
right child
の
max node
で
right subtree
で、このプロパティを順次走査に使用します。しかし、その先には迷いがあります。
EDIT
こんな付属のc++のコードを発見。ツリーを修正した後、どのように復元するのか理解するのに苦労しました。このマジックは
else
節があり、これは右の葉が変更されるとヒットする。詳しくはコードをご覧ください。
/* Function to traverse binary tree without recursion and
without stack */
void MorrisTraversal(struct tNode *root)
{
struct tNode *current,*pre;
if(root == NULL)
return;
current = root;
while(current != NULL)
{
if(current->left == NULL)
{
printf(" %d ", current->data);
current = current->right;
}
else
{
/* Find the inorder predecessor of current */
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;
/* Make current as right child of its inorder predecessor */
if(pre->right == NULL)
{
pre->right = current;
current = current->left;
}
// MAGIC OF RESTORING the Tree happens here:
/* Revert the changes made in if part to restore the original
tree i.e., fix the right child of predecssor */
else
{
pre->right = NULL;
printf(" %d ",current->data);
current = current->right;
} /* End of if condition pre->right == NULL */
} /* End of if condition current->left == NULL*/
} /* End of while */
}
解決方法は?
もし私がこのアルゴリズムを正しく読んでいるならば、これがその動作の例となるはずです。
X
/ \
Y Z
/ \ / \
A B C D
最初に
X
はルートなので、初期化されます。
current
.
X
は左の子を持っているので
X
の右端の右子として作成されます。
X
の左サブツリーの直前である。
X
を、順を追って探索する。そのため
X
の右の子として作成されます。
B
であれば
current
が設定されます。
Y
. これで、ツリーは次のようになります。
Y
/ \
A B
\
X
/ \
(Y) Z
/ \
C D
(Y)
上記は
Y
とその子供たち全てです。再帰の問題で省略されています。重要な部分はとにかくリストアップする。
さて、このツリーにはXへのリンクがあるので、探索を続ける...。
A
\
Y
/ \
(A) B
\
X
/ \
(Y) Z
/ \
C D
次に
A
が出力されるのは、左の子がいないからであり
current
が返され
Y
されたものである。
A
の右の子である。次の反復では、Yは両方の子を持つ。しかし、ループの二重条件により、ループは自分自身に到達すると停止する。これは、自分自身の左部分木がすでに走査されたことを示している。そこで、ループは自分自身を表示し、右の部分木である
B
.
B
は自分自身を印刷し、その後
current
になります。
X
と同じチェックプロセスを経ます。
Y
は、その左側のサブツリーがトラバースされたことも認識し、続けて
Z
. 残りのツリーも同じパターンになります。
再帰は必要ない。なぜなら、スタックをバックトラックする代わりに、(サブ)ツリーのルートへのリンクは、再帰的な木探索アルゴリズムでアクセスされるであろうポイント、つまり左サブツリーが終了した後に移動されるからである。
関連
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み] [Solved] インクルードファイルが開けません。'stdio.h' - Visual Studio Community 2017 - C++ Error
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】Eclipse IDEでC++エラー「nullptrはこのスコープで宣言されていません」が発生する件
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された