web-dev-qa-db-ja.com

ルートからバイナリツリーの特定のノードへのパスを取得する方法は?

ルートからバイナリツリーの特定のノードへのパスを取得する方法を見つけようとしています。

二分探索木ではありません。

各非リーフノードには、子へのポインターが2つだけあります。

インオーダー、プレオーダー、ポストオーダートラバーサルは機能しません。

予約注文をしようとしましたが、方法がわかりません。たとえば、二分木があります。これは二分探索木ではありません。パスを見つけやすくするために、並べ替え順序ノードを使用します。

     1 
   /   \
  2     3
 / \   / \
4   5 6   7 

1から7までのパスを見つけたい:

予約注文で、私たちは持っています:

1 -> 2 -> 4 -> 5 -> 3 -> 6 -> 7 

フローから、すべてのノードを含む1-> 7のパスを取得します。

明らかに、そうではないはずです。

どんな助けでも本当にありがたいです。

18
dtustudy68

プレオーダートラバーサル、別名深さ優先検索does work。

  • プレオーダートラバーサルを再帰的に実装する場合、目的のノードに到達したら、(再帰呼び出しの)スタックを巻き戻し、逆にパスを構築できます。

  • プレオーダートラバーサルを非再帰的に実装すると、スタックが直接構築されるため、この場合、目的のノードに到達すると、パスが既に存在します。

上記の質問のツリーでは、1から7までのパスを見つけるアルゴリズムは次のように進行します。

  • 1から始めて、スタックにプッシュします。スタックは[1]になります。
  • 左に2に移動し、スタックにプッシュします。スタックは[12]になります。
  • 4に左に移動し、プッシュします。スタックは[1 24]になります。
  • 4の子はありません、そしてそれはあなたが望むものではないので、それをポップしてください、スタックは今[1 2]
  • 2に戻ったので、すでに左に行き、右に行き、スタックは[1 25]になります。
  • 5の子はないので、ポップ、スタックは[1 2]
  • あなたは2人の子供を使い果たしたので、それをポップして、スタックは今[1]です。
  • これで1に戻り、左を終えたので、右に3に進み、プッシュすると、スタックは[1 3]になります。
  • 左に行くと、スタックは[1 3 6]
  • 6は葉であり、探しているものではないので、ポップ、スタックは[1 3]
  • 今、あなたは3から右に行かなければなりません、それを押してください、スタックは今[1 37]です
  • ちょっと待って!見て!探しているノードに到着しました!そして、あなたのスタックを見てください!それはあなたが望む道です。
27
Ray Toal

二分木(ルートノード)が与えられ、ツリーにある場合とない場合があるキーが与えられます。ルートからノードまでのフルパスを見つける必要があります。

例:

                A
           /           \
       B                C
         \               /
          D           E
        /    \           \
      K      L        M
    /
Z

ノードZ(またはNode)のキー)とNode A(root)のキーを指定したので、出力は次のようになります。

A B D K Z

mが指定されている場合、出力はA C EMになります。

public class main_class {
public static void main(String args[] ) {

    //first create tree
    Node rootNode = new Node ('A' , new Node('B',null,
                                             new Node('D',
                                                      new Node('K',
                                                               new Node('Z',null,
                                                               null),null),
                                                      new Node('L',null,null))),
                                    new Node('C',
                                             new Node('E',
                                                      null,
                                                      new Node('M',null,null)),null) );

    ArrayList <Node> path = new ArrayList<Node>();
    System.out.println(getPath(rootNode,'Z',path));
    System.out.println(path);
    path = new ArrayList<Node>();
    System.out.println(getPath(rootNode,'M',path));
    System.out.println(path);

}
static boolean getPath(Node rootNode, char key, ArrayList<Node> path ){
    //return true if the node is found
    if( rootNode==null)
        return false;
    if (rootNode.getVal()==key){
        path.add(rootNode);
        return true;
    }
    boolean left_check = getPath( rootNode.left,key,path);
    boolean right_check = getPath( rootNode.right,key,path);
    if ( left_check || right_check){
        path.add(rootNode);
        return true;
    }
    return false;

}
static class Node {
    char val;
    Node left;
    Node right;
    public Node( char val, Node left, Node right){
        this.left=left;
        this.right=right;
        this.val=val;
    }
    public char getVal(){
        return val;
    }
   public String toString(){
        return " " + val + " ";
    }
}

}
6
user2398113

次のツリーについて考えてみます。

       10
     /   \
    8      2
  /  \    /
3     5  2

アプローチ

  • ルートから開始してキーと比較し、一致する場合はパスを出力します(ツリーにノードが1つしかない場合、パスにはルートのみが含まれます)。
  • それ以外の場合、ノードをベクターにプッシュします(パスを格納するためのベクターを検討しました)。
  • 再帰的にツリーの左右に移動します。

次のコードが役立ちます。

     void PrintPath(node* root, vector <int> v,int key)
     {
      if(!root)
      return;
      if(root->data==key)
        {
          v.Push_back(root->data);
          vector<int>:: iterator it;
          for(it=v.begin();it<v.end();it++)
           {
             cout<<*it<<" ";
           }
            return;
        }
        v.Push_back(root->data);
        PrintPath(root->left,v,key);
        PrintPath(root->right,v,key);
    }    

説明

検出されるノードを、指定されたツリーの5(key)とします。

各ステップでのベクトルの内容:

  1. V = 10
  2. V = 10,8
  3. V = 10,8,3(3は検出されるキーではないため、バックトラックして右に移動します)
  4. V = 10,8,5(5がキーであるため、パスを出力します)。
1
Ruthwik

ここJavaには3つの解決策があります。
https://codereview.stackexchange.com/questions/105136/path-sum-in-binary-tree
最初に再帰的アプローチ、2番目に2つのサットを使用するアプローチ、最後に2つのキューを使用するアプローチ。お役に立てれば

0
Hengameh