【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; Queuequeue = 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 } }