バイナリ検索ツリーのトラバーサル検索(Java実装)

1.
二分探索木の概念二分探索木は二分木で構成されており、そのような木は、各ノードがオブジェクトであるリンクリストのデータ構造で表すことができます。
ここに画像の説明を挿入

2.バイナリサーチツリーノードオブジェクトの属性
(1)キー(オブジェクト全体を表すために使用されるキーワード)
(2)基本データおよび情報
(3)左、右、およびp、それぞれノードの左の子ノードを指す、右の子ノード、親ノード(親ノードの使用量が少ない場合は省略できます)

 class TreeNode {
    
    
      int key; //关键字
      TreeNode left; //左节点
      TreeNode right;  //右节点
      TreeNode() {
    
    }
      TreeNode(int val) {
    
     this.val = val; }
      TreeNode(int val, TreeNode left, TreeNode right) {
    
    
          this.val = val;
          this.left = left;
          this.right = right;
      }
  }

3.二分探索木の最も基本的な構築規則
どのノードノードでも、左側のサブツリーの各ノードのキーはnode.keyより大きくできず、右側のサブツリーの各ノードのキーはnode.keyより小さくできません。 。この構築ルールは、二分探索木のプロパティにつながる可能性があります。childNodeがノードの左側のサブツリーのノードである場合、childNode.key <= node.keyが同様に、右側のサブツリーにある場合、 childNode.key> = node.key。

4.バイナリツリー検索のトラバーサル
(1)バイナリツリーのトラバースには、BFS幅検索トラバーサルとDFSディープ検索トラバーサルの2つの主要な方法があります。幅検索トラバーサルのコアは、キューのデータ構造のアプリケーションです。ディープ検索トラバーサルには、 2つの方法があります。1つは再帰関数の設計をトラバースする方法、もう1つはスタックデータ構造を使用してトラバースする方法です。

1> DFS

//递归遍历
 public void search(TreeNode root){
    
    
        
        if(root==null)
           return;
        search(root.left);
        search(root.right);
    }
  //利用栈进行遍历
  public void search(TreeNode root){
    
    
     public void search(TreeNode root) {
    
    
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                DFS.push(node);
                node = node.left;
            }
            node = DFS.pop().right;
        }
    }
 }

2> BFS

 //利用队列进行遍历
 public void search(TreeNode root){
    
    
        TreeNode node=root;
        Queue<TreeNode>DFS=new LinkedList<>();
        DFS.offer(node);
        while(!DFS.isEmpty()||node!=null){
    
    
            node=DFS.poll();
            if(node.left!=null) 
                DFS.offer(node.left);
            if(node.right!=null) 
                DFS.offer(node.right);
        }

}

(2)バイナリツリートラバーサルの高度なアルゴリズム:モリスアルゴリズム。Morrisアルゴリズムは、バイナリサーチツリーを走査する際のスペースの複雑さを大幅に軽減します。アルゴリズムは主に、バイナリサーチツリーに存在する必要がある多数の空のノードを使用します(エンドノードには空のノードが必要)またはキュー。

アルゴリズムの主なステップ:

1>。バイナリ検索ツリーの子ノードについて、ノードに左の子がない場合は、ノードの右の子にアクセスし、ノードに左の子がある場合は、ノードの左のサブツリー(つまり、ノードの左のサブツリー)で最も右のノードを見つけます。シーケンストラバーサルの最後のノード)がmorrisBackとして記録されます。

2>。morrisBackの右の子が空かどうかに応じて、次の操作を実行します。右の子が空の場合は、右の子をノードにポイントしてから左の子にアクセスします。右の子が空でない場合は、ノードをたどったことを意味します左側のサブツリーについては、morrisBackの右側の子を空のままにして(バイナリ検索ツリーの構造を破壊しないようにするため)、ノードの右側の子にアクセスします(サブツリーのヘッドノードに戻るか、右側のノードにアクセスします)。

3>。完全なツリーが表示されるまで上記の操作を繰り返します。

モリスアルゴリズム図:
画像のソース
ここに画像の説明を挿入

class Solution {
    
    
    public void Search(TreeNode root) {
    
    
        TreeNode node=root;
        TreeNode morrisBack;
        while(node!=null){
    
    
            
            if(node.left!=null){
    
    
                morrisBack=node.left;
               
                while(morrisBack.right!=null&&morrisBack.right!=node)
                    morrisBack=morrisBack.right;
                
                if(morrisBack.right==null){
    
    
                    morrisBack.right=node;
                    node=node.left;
                }
                else{
    
    
                    morrisBack.right=null;
                    node=node.right;
                }
            }
            
            else
                node=node.right;


        }

    }
}

5.
二分木のトラバーサル分類二分木のトラバーサルアルゴリズムには、3つの特別な形式があり、前順トラバーサル、中次トラバーサル、および後続のトラバーサルです。
プリオーダートラバーサルの場合、これは、現在のノードの場合、最初にノード、次に左の子、最後に右の子にアクセスすることを意味します。
順序トラバーサルの場合、現在のノードでは、最初に左の子にアクセスし、次にノードにアクセスし、最後に右の子にアクセスします。(二分探索木の場合、中位のトラバーサルはノードのキー値の昇順でアクセスされ、ノードのキー値の昇順の配列を取得できます。)
後続のトラバーサルでは、現在のノードが最初です左の子、次に右の子、最後にノードにアクセスします。
ここに画像の説明を挿入
上の図の二分探索木を例にとります:

予約注文トラバーサル:

//递归算法
class Solution {
    
    
    public void search(TreeNode root) {
    
    
        if(root ==null)
            return;
        System.out.print(root.val+" ");
        search(root.left);
        search(root.right);
    }
}
//非递归算法
 public void search(TreeNode root) {
    
    
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                System.out.print(node.val+" ");
                DFS.push(node);
                node = node.left;
            }
            node = DFS.pop().right;
        }
    }

出力結果:6 5 2 5 7 9 8

順序トラバーサル:

//递归算法
class Solution {
    
    
    public void search(TreeNode root) {
    
    
        if(root ==null)
            return;
        search(root.left);
        System.out.print(root.val+" ");
        search(root.right);
    }
}
//非递归算法
 public void search(TreeNode root) {
    
    
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                DFS.push(node);
                node = node.left;
            }
            node = DFS.pop();
            System.out.print(root.val+" ");
            node=node.right; 
        }
    }

出力結果:2 5 5 6 7 8 9

注文後の走査:

//递归算法
class Solution {
    
    
    public void search(TreeNode root) {
    
    
        if(root ==null)
            return;
        search(root.left);
        search(root.right);
        System.out.print(root.val+" ");
    }
}
//非递归算法
public void search(TreeNode root) {
    
    
        HashMap<TreeNode,Integer>check=new HashMap<>();
        TreeNode node = root;
        Stack<TreeNode> DFS = new Stack<>();
        while (!DFS.isEmpty() || node != null) {
    
    
            while (node != null) {
    
    
                check.put(node,1);
                DFS.push(node);
                node = node.left;
            }

            node=DFS.peek();
            if(check.get(node)==1){
    
    
                check.put(node,2);
                node=node.right;
            }
            else{
    
    
                DFS.pop();
                System.out.print(node.val+" ");
                node=null; 
            }
        }
    }

出力結果:2 5 5 8 9 7 6

おすすめ

転載: blog.csdn.net/CY2333333/article/details/107882185