【Java】階層的なデータ構造の探索(ツリー探索)

【Java】階層的なデータ構造の探索(ツリー探索)

ツリー探索の概要

ツリー探索は、階層的なデータ構造であるツリーの各ノードを探索する方法を指します。ツリーは親子関係を持つノードが階層的に繋がった構造であり、データ構造の中でもよく使われます。探索アルゴリズムは、ツリーのノードを辿って、特定の条件に合致するノードを見つけるために使用されます。

ツリー構造の基本

ツリー構造にはいくつかの重要な要素があります。

  • ルートノード(根): ツリーの最上部にあるノードで、親を持たない唯一のノード。
  • 子ノード: 親ノードに直結しているノード。
  • 葉ノード: 子を持たないノード。
  • 親ノード: 1つ以上の子ノードを持つノード。

例えば、以下のようなツリー構造があります:

         A
        / \
       B   C
      / \   \
     D   E   F
    

このツリーでは、Aがルートノードで、BとCはAの子ノード、DとEはBの子ノード、FはCの子ノードです。

深さ優先探索(DFS)

深さ優先探索(DFS)は、ツリーまたはグラフの探索方法の一つで、ノードを深く掘り下げてから戻る方式です。具体的には、まず最も深いノードを探索し、そこから親ノードに戻り、未探索のノードがあれば再度深く探索します。DFSは再帰的に実装されることが多いです。

DFSの実装の基本的な流れは以下のようになります:

  • スタートノードから探索を始める。
  • ノードを訪問し、子ノードがあればその子ノードを訪問する。
  • 全ての子ノードを訪問したら親ノードに戻り、別の子ノードを訪問する。
  • 全てのノードを訪問したら終了する。

以下はDFSの簡単なJava実装例です:

public class DFS {
    class Node {
        int value;
        Node left, right;
        Node(int item) {
            value = item;
            left = right = null;
        }
    }
    
    void DFS(Node root) {
        if (root == null) return;
        System.out.print(root.value + " ");
        DFS(root.left);
        DFS(root.right);
    }
    
    public static void main(String[] args) {
        DFS tree = new DFS();
        Node root = tree.new Node(1);
        root.left = tree.new Node(2);
        root.right = tree.new Node(3);
        root.left.left = tree.new Node(4);
        root.left.right = tree.new Node(5);
        tree.DFS(root);
    }
}
    

このコードは、深さ優先でノードを探索し、ノードの値を表示します。

幅優先探索(BFS)

幅優先探索(BFS)は、ツリーまたはグラフの探索方法の一つで、最初に親ノードを訪問し、その後に子ノードを訪問していきます。BFSはキューを使用して、現在探索中のノードの隣接ノードを順次キューに追加し、探索を続けます。

BFSの実装の基本的な流れは以下の通りです:

  • スタートノードをキューに追加する。
  • キューからノードを取り出して、そのノードの全ての子ノードをキューに追加する。
  • キューが空になるまで、次のノードをキューから取り出し続ける。

以下はBFSの簡単なJava実装例です:

import java.util.LinkedList;
import java.util.Queue;

public class BFS {
    class Node {
        int value;
        Node left, right;
        Node(int item) {
            value = item;
            left = right = null;
        }
    }

    void BFS(Node root) {
        if (root == null) return;
        Queue queue = new LinkedList<>();
        queue.add(root);
        
        while (!queue.isEmpty()) {
            Node node = queue.poll();
            System.out.print(node.value + " ");
            if (node.left != null) queue.add(node.left);
            if (node.right != null) queue.add(node.right);
        }
    }
    
    public static void main(String[] args) {
        BFS tree = new BFS();
        Node root = tree.new Node(1);
        root.left = tree.new Node(2);
        root.right = tree.new Node(3);
        root.left.left = tree.new Node(4);
        root.left.right = tree.new Node(5);
        tree.BFS(root);
    }
}
    

このコードは、幅優先でノードを探索し、ノードの値を表示します。

二分探索木(BST)

二分探索木(BST)は、各ノードが最大2つの子ノードを持ち、左の子ノードは親ノードより小さく、右の子ノードは親ノードより大きいという特性を持つツリーです。これにより、効率的に探索を行うことができます。

BSTの探索は、ターゲットノードの値を比較し、左か右のサブツリーを再帰的に探索する方法です。

実際のJavaコード例

実際の二分探索木(BST)における探索例を示します。以下のコードでは、挿入と探索の操作を行います:

class BST {
    class Node {
        int value;
        Node left, right;
        Node(int item) {
            value = item;
            left = right = null;
        }
    }
    
    Node root;
    
    BST() {
        root = null;
    }

    void insert(int value) {
        root = insertRec(root, value);
    }

    Node insertRec(Node root, int value) {
        if (root == null) {
            root = new Node(value);
            return root;
        }
        
        if (value < root.value)
            root.left = insertRec(root.left, value);
        else if (value > root.value)
            root.right = insertRec(root.right, value);

        return root;
    }

    boolean search(Node root, int value) {
        if (root == null) return false;
        if (root.value == value) return true;
        
        if (value < root.value)
            return search(root.left, value);
        else
            return search(root.right, value);
    }
    
    public static void main(String[] args) {
        BST tree = new BST();
        tree.insert(50);
        tree.insert(30);
        tree.insert(20);
        tree.insert(40);
        tree.insert(70);
        tree.insert(60);
        tree.insert(80);
        
        System.out.println(tree.search(tree.root, 40)); // true
        System.out.println(tree.search(tree.root, 100)); // false
    }
}
    

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です