二分木の再帰的および非再帰的トラバーサルアルゴリズムテンプレート

二分木の再帰的および非再帰的トラバーサルアルゴリズムテンプレート

[[423968]]

Leetcode を実践するには、いくつかのアルゴリズム テンプレートを知っておく必要があります。今回は、まず二分木の再帰的および非再帰的トラバーサル アルゴリズム テンプレートをまとめます。

バイナリ ツリーをトラバースする方法には、前方トラバース、中間トラバース、後方トラバース、レベル順トラバースの 4 つがあります。バイナリ ツリーのフロント、ミドル、バックの順序のトラバーサルでは、各トラバーサルを再帰的および循環的に実装することができ、各トラバーサルの再帰的実装は循環的実装よりも簡単です。以下に簡単にまとめておきます。私は「Code Thoughts」のハルビン工業大学の先輩の問題解決ガイドに深く感銘を受けました。そのため、以下のコードは「Code Thoughts」から一部引用したものです。

再帰

次の疑似コードは、二分木トラバーサルの再帰アルゴリズム テンプレートです。順序は中央、左、右で、前順序トラバーサルです。3 行のコード順序を変更することで、前順序、中央順序、後順序の 3 つの再帰トラバーサルを簡単に解決できます。

  1. def preorderTraversal(ルート: TreeNode) -> List[ int ]:
  2. 解像度 = []
  3. defヘルプ(ルート):
  4. ルートでない場合は戻る 
  5. res.append(ルート.val) #
  6. help( root.left ) # 左
  7. ヘルプ( root.right ) # 右
  8. ヘルプ(ルート)
  9. 戻り

これには C++ コードも用意されています。再帰アルゴリズム テンプレートには終了条件を追加する必要があります。そうしないと、再帰に入ると、深海に入るようなものになり、それ以降は、オファーは通行人になります。ソース コードのランダムな考え。

  1. void help(TreeNode * ルート、ベクトル< int > &res) {
  2. ルート == nullptr の場合 {
  3. 戻る;
  4. }
  5. res.push_back(root->val); // 中間
  6. help(root-> left ,res); // 左
  7. help(root-> right ,res); //右
  8. }
  9.  
  10.  
  11. ベクトル< int > preorderTraversal(TreeNode* ルート) {
  12. ベクトル< int > res;
  13. ヘルプ(ルート、res);
  14. resを返します
  15. }

反復

バイナリ ツリーの反復トラバーサルは、再帰トラバーサルよりも困難です。実際、スタック データ構造が使用されます。「Code Thoughts」では、マーキングにヌル ポインターを巧みに使用しています。原則として、処理されたノードをスタックに配置し、ヌル ポインターをマークとして配置します。

スタックは先入れ後出しの順序になっているため、事前順序トラバーサルの順序は左と右です。スタックに追加するときは、逆の順序で追加する必要があります。追加する各要素の後に null ポインターを追加します。Python では、代わりに None を使用することもできます。

以下は具体的な疑似コードです。インオーダートラバーサルとポストオーダートラバーサルについては、スタックにノードを追加する順序を変更するだけです。

  1. def preorderTraversal(ルート: TreeNode) -> List[ int ]:
  2. 結果 = []
  3. st=[]
  4. # 1. ルートを決定する
  5. ルートの場合:
  6. st.append(ルート)
  7. 一方、st:
  8. ノード = st.pop()
  9. ノードが None の場合:
  10. # 右、左、中央をスタックに追加し、中央、左、右を取り出します
  11. node.rightの場合: #right
  12. st.append(ノード右)
  13. node.leftの場合: #left
  14. st.append(ノード.left )
  15. st.append(ノード) #
  16. # ノードを記録するためにヌルポインタを追加します
  17. st.append(なし)
  18. それ以外
  19. # ノードはヌルポインタなので、次のノードが追加されます
  20. ノード = st.pop()
  21. 結果を追加します(node.val)
  22. 結果を返す

以下は具体的な C++ コードです。C++ ではスタックにポップした後に戻り値がないので、特に注意が必要です。

  1. ベクトル< int > preorderTraversal(TreeNode* ルート) {
  2. ベクトル< int >res;
  3. スタック<TreeNode*> st;
  4. ルートが nullptr ではない場合、st.push(root);
  5. while(!st.empty()){
  6. TreeNode* ノード = st.top ();
  7. if(ノード ​​!= nullptr){
  8. st.pop();
  9. if(node-> right ) st.push(node-> right );
  10. ノードが左にある場合、st.push(ノードが左にある)。
  11. st.push(ノード);
  12. st.push( NULL );
  13. }それ以外{
  14. // 特別な注意が必要
  15. st.pop();
  16. ノード = st.top ();
  17. st.pop();
  18. res.push_back(ノード->val);
  19. }
  20. }
  21. resを返します
  22.      
  23. }

階層トラバーサル

実際、ツリー トラバーサルには、深さ優先トラバーサルと幅優先トラバーサルの 2 種類があります。ツリーのさまざまな深さ優先トラバーサル (前順序、内順序、後順序トラバーサル) は、再帰的および非再帰的な記述方法です。ツリー内の幅優先トラバーサルは、レベルごとのトラバーサルです。

バイナリ ツリーの階層的トラバーサルでは、トラバーサルを完了するためにキュー データ構造を使用する必要があります。

Pythonの擬似コードでは、

  1. def levelOrder(root: TreeNode) -> List[List[ int ]]:
  2. # 1. ルートを決定する
  3. ルートでない場合:
  4. 戻る[]
  5. # キューにルートを追加する
  6. quene = [ルート]
  7. 出力リスト = []
  8. 一方、クエン:
  9. # 最初のステップは長さを見つけることです
  10. 長さ = len(キュー)
  11. in_list = []
  12. _が範囲(長さ)の場合:
  13. # C++では2行必要
  14. curnode = queue.pop(0) # (デフォルトではリストの最後の要素を削除します) ここではキューの先頭にある要素を削除する必要があります
  15. in_list.append(curnode.val)
  16. curnode.left場合: queue.append( curnode.left )
  17. curnode.right場合: queue.append( curnode.right )
  18. out_list.append(in_list)
  19. out_listを返す

上記の Python 疑似コードを使用して、より効率的な C++ コードを記述します。

  1. クラスソリューション{
  2. 公共
  3. ベクトル<ベクトル< int >> レベルオーダー(TreeNode* ルート) {
  4. ベクトル<ベクトル< int >> res;
  5. キュー<TreeNode*> que;
  6. // ルートを決定する
  7. root != nullptr の場合、que.push(root);
  8. while(!que.empty()) {
  9. // まずキューの長さを調べます
  10. 整数 サイズ= que.size ( );
  11. ベクトル< int > vec;
  12. // 反復してノード要素を追加する
  13. ( int i = 0 ; i<サイズ; i++) {
  14. TreeNode* ノード = que.front();
  15. que.pop();
  16. vec.push_back(ノード->val);
  17. if (node-> left ) que.push(node-> left );
  18. node-> rightの場合、que.push(node-> right ) を実行します。
  19. }
  20. res.push_back(vec);
  21. }
  22. resを返します
  23. }
  24. };

上記はツリートラバーサルテンプレートです。実際、これは本質的には深さ優先探索と幅優先探索のアルゴリズム テンプレートです。他の多くの操作はツリー探索操作に基づいています。したがって、すべてのツリー探索方法を習得することは、ツリー問題の半分を解決することと同じです。

<<:  毎日のアルゴリズム: 二分木のレベルトラバーサル

>>:  暗号化アルゴリズムの革命的な進歩、データ保護の問題を解決するか?

ブログ    
ブログ    

推薦する

ロボティック プロセス オートメーション (RPA): 6 つのオープン ソース ツール

[[321682]] [51CTO.com クイック翻訳] 多くの新しいソフトウェアを実装する場合と...

企業に利益をもたらす 5 つの AI トレンド

[[358096]]市場の状況がますます複雑化する今日の不安定なビジネス環境では、組織が分析に基づく...

今後のネットワーク分野におけるハイブリッド脅威の3大トレンド

人工知能の破壊的応用の増加、危機時のネットワークの役割の拡大、ポリシーとテクノロジー間の依存関係の高...

これはボストンダイナミクスのロボット犬の父親でしょうか?米陸軍の1980年代のロボット犬「考古学」

この高さ3メートルの巨大ロボットは、ボストン・ダイナミクスのロボット犬より20年以上も前の1980年...

機械学習は将来どこに向かうのでしょうか?インテル・南京大学共同研究センターが答えを提供する

[51CTO.com からのオリジナル記事] 人工知能アルゴリズムに関しては、ディープラーニングが現...

AIのダークサイドを暴く:人工知能は人間に取って代わるが、機械をどのように学習するかは分からない

[[189044]]昨年、自動運転車がニュージャージー州モンマス郡に侵入した。チップメーカーのNvi...

...

...

CPU、GPU、NPU、FPGA はディープラーニングでどのように優位性を発揮するのでしょうか?

AIの応用が広まるにつれ、ディープラーニングは現在のAI研究と応用の主流の方法となっています。膨大...

WeBank AI 主任科学者 NeurIPS の論文で「最新のニューラル ネットワーク盗難防止技術」が明らかに

保護されていないニューラル ネットワークは、誰でも運転できるロックされていない車のようなものです。...

小さくても素晴らしい、ミニプログラムのデビュー

[51CTO.comより引用] 2017年1月9日にWeChatミニプログラムが正式リリースされて以...

...