データ構造とアルゴリズム (Java Edition) データ構造の知識ポイント

データ構造:

  1. 配列: 同じタイプの要素のセットを格納できる線形データ構造。Java の配列は固定長であり、配列内の要素には添字を使用してアクセスできます。

  2. リンク リスト: 一連のノードで構成される線形データ構造。各ノードにはデータ要素と次のノードへのポインターが含まれます。Java では、LinkedList を使用して単一リンク リストを実装したり、カスタム クラスを使用して二重リンク リストを実装したりできます。

  3. スタック: 配列またはリンク リストを使用して実装できる後入れ先出し (LIFO) データ構造。スタックは、Stack クラスを使用して Java で実装できます。

  4. キュー: 配列またはリンク リストを使用して実装できる先入れ先出し (FIFO) データ構造。Java では、Queue インターフェイスを使用してキューを実装したり、LinkedList を使用して両端キューを実装したりできます。

  5. ツリー: ノードとノード間の接続で構成される非線形データ構造。Java では、TreeNode クラスを使用してバイナリ ツリーを実装したり、カスタム クラスを使用して他のタイプのツリーを実装したりできます。

  6. ヒープ: ヒープ特性 (大きなルート ヒープまたは小さなルート ヒープ) を満たす特別なツリー データ構造。Java では、PriorityQueue を使用してヒープを実装できます。

  7. グラフ: 一連のノードとそれらの間の接続で構成される非線形データ構造。グラフは、カスタム クラスを使用して Java で実装できます。

目次

配列

リンクされたリスト

スタック

ヒープ

写真


配列

配列に関する共通の知識事項は次のとおりです。

  1. 配列を定義する: 配列を定義するには、配列タイプ、配列名、および配列長を指定する必要があります。たとえば、長さ 10 の整数配列を定義するには、次のコードを使用できます。

    int[] arr = new int[10];

  2. 配列の初期化: 配列を定義するときに初期化することも、プログラムの後半で配列要素に値を割り当てることもできます。たとえば、文字列の配列を定義し、次のように初期化します。

    String[] names = {"Alice", "Bob", "Charlie"};

  3. 配列要素へのアクセス: 配列要素には添え字を介してアクセスできます。添字は 0 で始まり、配列の長さから 1 を引いた長さで終わります。たとえば、上で定義した名前配列の最初の要素にアクセスするには、次のようにします。

    String name = names[0];

  4. 多次元配列: Java では、2 次元配列、3 次元配列などの多次元配列を定義できます。2 次元配列を定義するには、配列タイプ、配列名、行数、列数を指定する必要があります。たとえば、3 行 4 列の 2 次元整数配列を定義します。

    int[][] arr = new int[3][4];

  5. 配列の長さ: 配列の長さは、配列の長さプロパティを通じて取得できます。たとえば、上で定義した名前配列の長さを取得するには、次のようにします。

    int len = names.length;

  6. 配列の走査: for ループまたは foreach ループを使用して、配列内の要素を走査できます。たとえば、foreach ループを使用して、上で定義した名前配列内のすべての要素を反復処理します。

    for (String name : names) { System.out.println(name); }
  7. 配列の並べ替え: Arrays クラスの sort メソッドを使用して配列を並べ替えることができます。たとえば、整数の配列を並べ替えるには次のようにします。

    int[] arr = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3}; Arrays.sort(arr);
  8. 配列のコピー: Arrays クラスの copyOf メソッドを使用して配列をコピーできます。たとえば、整数の配列を新しい配列にコピーするには、次のようにします。

    int[] arr = {1, 2, 3, 4, 5}; int[] newArr = Arrays.copyOf(arr, arr.length);

    リンクされたリスト

リンク リストは、キュー、スタック、その他の高度なデータ構造を実装するために使用できる基本的なデータ構造です。Java では、リンク リストは通常​​、Node オブジェクトによって表されます。各ノードにはデータ要素と次のノードへの参照が含まれています。データ構造とアルゴリズム (Java Edition) のリンク リストに関する知識ポイントを以下に示します。

1. リンク リストの基本構造: リンク リストはノードで構成され、各ノードにはデータ要素と次のノードへの参照が含まれます。次のように:

class Node {
    int data;       // 数据元素
    Node next;      // 指向下一个节点的引用
}

リンク リストの定義: リンク リストはノードで構成され、各ノードにはデータ要素と次のノードへのポインターが含まれます。

public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
}

2. リンク リストのトラバース: リンク リストのトラバースとは、リンク リスト内の各ノードを順番に訪問することを指します。リンクされたリストは、ループまたは再帰を使用して走査できます。次のように:

// 使用循环方式遍历链表
Node current = head;
while (current != null) {
    // 访问当前节点的数据元素
    System.out.print(current.data + " ");
    // 将当前节点移动到下一个节点
    current = current.next;
}

// 使用递归方式遍历链表
public void traverse(Node node) {
    if (node != null) {
        // 访问当前节点的数据元素
        System.out.print(node.data + " ");
        // 递归访问下一个节点
        traverse(node.next);
    }
}

 リンク リストのトラバーサル: リンク リストの先頭ノードから開始して、末尾ノードまで各ノードを順番に訪問します。

ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
ListNode cur = head;
while (cur != null) {
    System.out.print(cur.val + " ");
    cur = cur.next;
}
// 输出:1 2 3

3. リンクリストの挿入操作: リンクリストの挿入操作とは、リンクリストに新しいノードを挿入することを指します。挿入動作は頭部挿入方式と尾部挿入方式に分けられます。次のように:

// 头插法:将新节点插入到链表的头部
Node newNode = new Node(5);
newNode.next = head;
head = newNode;

// 尾插法:将新节点插入到链表的尾部
Node newNode = new Node(5);
if (head == null) {
    head = newNode;
} else {
    Node current = head;
    while (current.next != null) {
        current = current.next;
    }
    current.next = newNode;
}

4. リンクリストの削除操作: リンクリストの削除操作とは、リンクリスト内のノードを削除することを指します。削除操作には通常、削除されるノードの先行ノードに関する知識が必要です。次のように:

// 删除指定节点
Node current = head;
Node prev = null;
while (current != null) {
    if (current.data == key) {
        if (prev == null) {
            // 要删除的节点是头节点
            head = current.next;
        } else {
            // 删除中间节点或尾节点
            prev.next = current.next;
        }
        return true;
    }
    prev = current;
    current = current.next;
}
return false;

ヘッド ノードを削除します。

head = head.next;

 末尾ノードを削除します。

ListNode cur = head;
while (cur.next.next != null) {
    cur = cur.next;
}
cur.next = null;

 指定したノードを削除します。

ListNode prev = null;
ListNode cur = head;
while (cur != null) {
    if (cur.val == target) {
        if (prev == null) {
            head = head.next;
        } else {
            prev.next = cur.next;
        }
        break;
    }
    prev = cur;
    cur = cur.next;
}

5. リンクリストの反転操作: リンクリストの反転操作とは、リンクリスト内のノードを反転することを指します。逆の操作では、通常、prev、current、next の 3 つのポインターを使用する必要があります。次のように:

public ListNode reverseList(ListNode head) {
    ListNode prev = null;
    ListNode current = head;
    ListNode next = null;

    while (current != null) {
        // 保存当前节点的下一个节点
        next = current.next;
        // 反转当前节点的指针,指向前一个节点
        current.next = prev;
        // 将prev指针指向当前节点
        prev = current;
        // 将current指针指向next节点,继续遍历链表
        current = next;
    }

    // prev指向的节点即为反转后的头节点
    return prev;
}

このアルゴリズムでは、最初に 3 つのポインター (prev、current、next) を定義します。prev は前のノードを指し、current は現在のノードを指し、next は現在のノードの次のノードを指します。ループでは、現在のノードの次のポインタが前のノードを指し、次に前のポインタが現在のノードを指し、現在のポインタが次のノードを指し、リンク リストの最後に到達するまでリンク リストのトラバースを続けます。最後に、prev が指すノードが反転ヘッド ノードです。

反転操作では、反転操作後にリンク リストの次のノードに移動できなくなるのを防ぐために、現在のノードの次のノードを事前に保存する必要があることに注意してください。

6. リンク リストの中間ノード: リンク リストの中間ノードを見つけるには、高速ポインタと低速ポインタの方法を使用できます。

ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null) {
    fast = fast.next.next;
    slow = slow.next;
}
return slow;

7. リンク リストのマージ: 2 つのソートされたリンク リストを 1 つのソートされたリンク リストにマージします。

このうち、ListNode はリンク リストのノード クラス、val はノードの値、next は次のノードへのポインタです。

public class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

public class LinkedList {
    public ListNode merge(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }
        ListNode head = null;
        if (l1.val < l2.val) {
            head = l1;
            head.next = merge(l1.next, l2);
        } else {
            head = l2;
            head.next = merge(l1, l2.next);
        }
        return head;
    }
}

このメソッドは、まず l1 と l2 が null かどうかを判断し、どちらかが null であれば、別のリンク リストを直接返します。次に、マージされたリンク リストのヘッド ノードとしてヘッド ノードを定義し、l1 と l2 の値を比較し、小さい方の値をヘッド ノードとして使用し、その次を再帰的にマージされたリンク リストにポイントします。最後に、ヘッド ノードに戻ります。

アルゴリズムの時間計算量は O(n) です。ここで、n は 2 つのリンクされたリスト内のノードの合計数です。

スタック

スタック(Stack)は、「先入れ後出し」の特徴を持つ線形データ構造です。スタックの挿入操作はプッシュと呼ばれ、削除操作はポップと呼ばれます。スタックには非常に重要な操作もあります。これは、スタックの最上位要素を表示しますが、スタックの外に出ることはなく、「スタックの最上位要素」(ピーク) と呼ばれます。

以下は、スタックに関する一般的な知識のポイントです。

  1. スタックの実装: スタックは配列またはリンク リストによって実装できます。

  2. スタック操作: スタックの主な操作には、スタック、ポップ、スタックが空かどうかの判断、スタックの最上位要素の表示などが含まれます。

  3. スタックのアプリケーション: スタックの一般的なアプリケーションには、式の評価、ブラケット マッチング、迷路解決、再帰関数の実装などがあります。

以下は、いくつかの一般的なスタック操作のサンプル コードです。

1. プッシュ操作

public void push(int val) {
    stack.add(val);
}

2. ポップ操作

public int pop() {
    if (stack.isEmpty()) {
        throw new EmptyStackException();
    }
    return stack.remove(stack.size() - 1);
}

3. スタックが空かどうかを確認します。

public boolean isEmpty() {
    return stack.isEmpty();
}

4. スタックの最上位要素を表示する

public int peek() {
    if (stack.isEmpty()) {
        throw new EmptyStackException();
    }
    return stack.get(stack.size() - 1);
}

キュー (Queue) は、先入れ先出し (FIFO) の特性を持つ線形データ構造です。キューには、エンキューとデキューという 2 つの基本操作があります。エンキュー操作はキューの最後に要素を挿入し、デキュー操作はキューの最初の要素を削除して返します。

Java で一般的に使用されるキューの実装クラスは次のとおりです。

1. LinkedList: LinkedList は Java 標準ライブラリの二重リンク リスト実装であり、キューとしても使用できます。LinkedList は Deque インターフェイスを実装しているため、両端キューとしても使用できます。

以下は、LinkedList を使用してキューを実装するサンプル コードです。

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

public class MyQueue {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(1); // 入队操作
        queue.offer(2);
        queue.offer(3);
        System.out.println(queue.peek()); // 获取队列头部元素
        System.out.println(queue.poll()); // 出队操作
        System.out.println(queue.poll());
        System.out.println(queue.poll());
    }
}

2. ArrayDeque: ArrayDeque は、キューおよびスタックとして使用できる配列ベースの両端キューです。

以下は、ArrayDeque を使用してキューを実装するサンプル コードです。

import java.util.ArrayDeque;
import java.util.Queue;

public class MyQueue {
    public static void main(String[] args) {
        Queue<Integer> queue = new ArrayDeque<>();
        queue.offer(1); // 入队操作
        queue.offer(2);
        queue.offer(3);
        System.out.println(queue.peek()); // 获取队列头部元素
        System.out.println(queue.poll()); // 出队操作
        System.out.println(queue.poll());
        System.out.println(queue.poll());
    }
}

3. PriorityQueue: PriorityQueue は、要素の優先度に従ってソートできる優先度ヒープ (最小ヒープ) に基づくキュー実装です。

以下は、PriorityQueue を使用してキューを実装するためのサンプル コードです。

import java.util.PriorityQueue;
import java.util.Queue;

public class MyQueue {
    public static void main(String[] args) {
        Queue<Integer> queue = new PriorityQueue<>();
        queue.offer(3); // 入队操作
        queue.offer(1);
        queue.offer(2);
        System.out.println(queue.peek()); // 获取队列头部元素
        System.out.println(queue.poll()); // 出队操作
        System.out.println(queue.poll());
        System.out.println(queue.poll());
    }
}

上記 3 つの実装メソッドに加えて、Java には BlockingQueue や ConcurrentLinkedQueue などのキュー実装クラスも用意されており、必要に応じて選択できます。

データ構造とアルゴリズム (Java バージョン) ツリーのすべてのナレッジ ポイント:

ツリーは非常に一般的なデータ構造です。n 個のノードの集合であり、各ノードには 0 個以上の子ノードがあります。親ノードのないノードはルート ノードと呼ばれます。ルート ノードを除く各子ノードには親ノードがあり、それらはエッジで接続されています。ツリー構造には適切な階層があり、通常はファイル システムや HTML ドキュメントなどの階層的に関連するデータを格納するために使用されます。

ツリーの基本概念:

  • ノード: ツリー内の基本単位。
  • ルート ノード: ツリーの最上位ノード。
  • 親ノード: ノードの直属の上位ノード。
  • 子ノード: ノードの直接の下位ノード。
  • リーフノード: 子ノードを持たないノード。
  • 兄弟ノード: 同じ親ノードを持つノード。
  • サブツリー: ノードとそのすべての子のコレクション。
  • 深さ: ルート ノードから現在のノードまでのパスの長さ。
  • 高さ: 現在のノードからリーフ ノードまでの最長パスの長さ。

ツリートラバーサル:

ツリー トラバーサルとは、ツリー内のすべてのノードを特定の順序で訪問するプロセスを指します。一般的なツリー走査方法は 3 つあります。

  1. 事前順序トラバーサル: 「ルート ノード - 左のサブツリー - 右のサブツリー」の順序で各ノードを訪問します。
  2. インオーダートラバーサル: 「左のサブツリー - ルートノード - 右のサブツリー」の順序で各ノードを訪問します。
  3. 事後走査: 「左のサブツリー - 右のサブツリー - ルート ノード」の順序で各ノードを訪問します。

ツリー トラバーサルは、再帰と反復の 2 つの方法で実装できます。

ツリーに対する一般的な操作:

  1. ノードの挿入: 新しいノードをツリーに挿入します。
  2. ノードの削除: ツリーからノードを削除します。
  3. ノードの検索: ツリー内の指定したノードを検索します。
  4. 木の高さを取得する: 木の高さを計算します。
  5. ツリー内のノードの数を取得する: ツリー内のノードの数を計算します。

ツリーの実装:

ツリーは、チェーン ストレージとアレイ ストレージを使用して実装できます。

リンク ストレージとは、ツリー内の各要素を表すノードの使用を指します。各ノードには、値、左の子ノード、右の子ノードの 3 つの部分が含まれます。

配列ストレージとは、配列を使用してツリー内の各要素を表し、配列の添え字を使用してノード番号を表し、各ノードに値が含まれることを指します。

一般的なツリー構造には、バイナリ ツリー、バイナリ サーチ ツリー、バランス ツリー、ヒープなどが含まれます。

上記は、データ構造とアルゴリズム (Java Edition) のツリーに関連する知識ポイントであり、ツリーの基本概念、走査、操作、実装が含まれます。

ヒープ

ヒープは完全なバイナリ ツリーであり、最大ヒープと最小ヒープの 2 つの形式があります。最大ヒープでは、親ノードの値は常にその子の値以上になります。ただし、min-heap では、親ノードの値は常にその子ノードの値以下になります。

ヒープは、PriorityQueue クラスを使用して Java で実装できます。PriorityQueue は優先キューであり、ヒープを使用して内部的に実装されます。追加および削除操作の時間計算量は O(logn) です。

一般的なヒープ操作には次のものがあります。

  1. 要素の追加: 新しい要素をヒープの最後に追加し、ヒープのプロパティを満たすようにヒープを上方に調整します。

  2. 要素の削除: ヒープの最上位要素を削除し、次にヒープの最後の要素をヒープの最上位に移動し、ヒープのプロパティに合うようにヒープを下方に調整します。

  3. ヒープの最上位要素を取得する: ヒープの最上位要素、つまりヒープ内の最大または最小の要素を返します。

以下は、PriorityQueue を使用してヒープを実装するサンプル コードです。

import java.util.PriorityQueue;

public class HeapExample {
    public static void main(String[] args) {
        // 创建一个最小堆
        PriorityQueue<Integer> minHeap = new PriorityQueue<>();

        // 添加元素
        minHeap.add(3);
        minHeap.add(1);
        minHeap.add(2);

        // 获取堆顶元素
        System.out.println(minHeap.peek()); // 输出1

        // 删除堆顶元素
        minHeap.poll();

        // 获取堆顶元素
        System.out.println(minHeap.peek()); // 输出2
    }
}

上記のコードは最小ヒープを作成し、3 つの要素を追加します。次に、 Peak() メソッドを使用してヒープの最上位要素を取得し、ヒープの最上位要素を削除して、ヒープの最上位要素を再度取得します。最終的な出力は 1 と 2 で、これはヒープの性質に準拠しています。

写真

グラフは、現実世界の多くの問題を表すために使用できるノード (または頂点) とエッジで構成されるデータ構造です。Java のグラフは、隣接行列または隣接リストを使用して表現できます。

Java のグラフに関するすべての知識ポイントは次のとおりです。

1. 隣接行列の表記法

隣接行列表記では、2 次元配列を使用して、グラフ内の各ノード間の関係を表します。2 次元配列の行と列はノードに対応し、各要素の値は対応するノード間にエッジがあるかどうかを示します。

サンプルコード:

public class Graph {
    private int[][] adjMatrix;
    private int vertexCount;

    public Graph(int vertexCount) {
        this.vertexCount = vertexCount;
        adjMatrix = new int[vertexCount][vertexCount];
    }

    public void addEdge(int i, int j, int weight) {
        adjMatrix[i][j] = weight;
        adjMatrix[j][i] = weight;
    }

    public void removeEdge(int i, int j) {
        adjMatrix[i][j] = 0;
        adjMatrix[j][i] = 0;
    }

    public int getEdge(int i, int j) {
        return adjMatrix[i][j];
    }

    public int getVertexCount() {
        return vertexCount;
    }
}

 2. 隣接リストの表記

隣接リスト表記では、配列を使用して各ノードの隣接ノードを格納します。配列内の各要素はノードに対応し、各要素はノードの隣接ノードを格納するリンク リストです。

サンプルコード:

public class Graph {
    private LinkedList<Integer>[] adjList;
    private int vertexCount;

    public Graph(int vertexCount) {
        this.vertexCount = vertexCount;
        adjList = new LinkedList[vertexCount];
        for (int i = 0; i < vertexCount; i++) {
            adjList[i] = new LinkedList<>();
        }
    }

    public void addEdge(int i, int j) {
        adjList[i].add(j);
        adjList[j].add(i);
    }

    public void removeEdge(int i, int j) {
        adjList[i].remove(Integer.valueOf(j));
        adjList[j].remove(Integer.valueOf(i));
    }

    public boolean hasEdge(int i, int j) {
        return adjList[i].contains(j);
    }

    public LinkedList<Integer> getAdjacentVertices(int i) {
        return adjList[i];
    }

    public int getVertexCount() {
        return vertexCount;
    }
}

3. 深さ優先トラバース

深さ優先トラバーサルは、グラフ内のノードから開始し、パスをたどってリーフ ノードに到達し、その後、前のノードに戻って次の子ノードへの訪問を続けます。深さ優先トラバーサルは再帰を使用して実装されます。

サンプルコード:

public void dfs(int start, boolean[] visited) {
    visited[start] = true;
    System.out.print(start + " ");
    for (int i : adjList[start]) {
        if (!visited[i]) {
            dfs(i, visited);
        }
    }
}

4. 幅優先トラバーサル

幅優先走査 (BFS) は、グラフを走査するためのアルゴリズムで、「幅優先検索」または「水平優先検索」とも呼ばれます。

幅優先走査は、グラフ内のノードから開始し、最初にこのノードに直接隣接するすべてのノードを訪問し、次にこのノードに直接または間接的に隣接するすべてのノードが走査されるまで層ごとに走査します。幅優先トラバーサルは通常、キューを使用して実装する必要があります。

以下は、Java で幅優先トラバーサルを実装するサンプル コードです。

import java.util.*;

public class Graph {
    private int V;              // 图的顶点数
    private LinkedList<Integer>[] adj;    // 邻接表表示图

    // 构造函数
    public Graph(int v) {
        V = v;
        adj = new LinkedList[v];
        for (int i = 0; i < v; i++) {
            adj[i] = new LinkedList<>();
        }
    }

    // 添加边
    public void addEdge(int v, int w) {
        adj[v].add(w);
    }

    // 广度优先遍历
    public void BFS(int s) {
        boolean[] visited = new boolean[V];
        LinkedList<Integer> queue = new LinkedList<>();
        visited[s] = true;
        queue.add(s);

        while (queue.size() != 0) {
            s = queue.poll();
            System.out.print(s + " ");

            Iterator<Integer> i = adj[s].listIterator();
            while (i.hasNext()) {
                int n = i.next();
                if (!visited[n]) {
                    visited[n] = true;
                    queue.add(n);
                }
            }
        }
    }

    // 测试代码
    public static void main(String[] args) {
        Graph g = new Graph(4);
        g.addEdge(0, 1);
        g.addEdge(0, 2);
        g.addEdge(1, 2);
        g.addEdge(2, 0);
        g.addEdge(2, 3);
        g.addEdge(3, 3);

        System.out.println("广度优先遍历 (从顶点 2 开始):");
        g.BFS(2);
    }
}

上記のサンプルコードでは、まずグラフを表現するための Graph クラスを定義します。このクラスでは、隣接リストを使用してグラフを表現します。隣接リストは、各頂点の隣接頂点のリストをリンク リストとして保存する、グラフを表現するための一般的なデータ構造です。

Graph クラスでは、addEdge メソッドを使用してエッジを追加し、BFS メソッドを使用して幅優先トラバーサルを実装します。BFS 法では、各頂点が訪問されたかどうかを記録するためにブール型の配列 Visited を使用し、訪問する頂点を格納するために LinkedList 型のキュー キューを使用します。まず開始頂点をキューに追加し、次にキュー内の各頂点を順番に走査し、隣接する未訪問の頂点をキューに追加して、それらを訪問済みとしてマークします。トラバーサルはキューが空になるまで終了します。

最後に、テスト コードでは、6 つの頂点を持つグラフを作成し、BFS メソッドを呼び出して幅優先トラバーサルを実装します。プログラムを実行すると、出力は次のようになります。

广度优先遍历 (从顶点 2 开始):
2 0 3 1

もっと詳しく:

以下は、頂点 2 から開始する幅優先トラバーサルの例です。

次のグラフがあるとします。

     2 —— 0
    / \
   1 —— 3

このグラフを隣接リストを使用して表現します。

import java.util.ArrayList;

public class Graph {
    private int V; // 顶点数
    private ArrayList<ArrayList<Integer>> adj; // 邻接表

    public Graph(int v) {
        V = v;
        adj = new ArrayList<>();
        for (int i = 0; i < v; i++) {
            adj.add(new ArrayList<Integer>());
        }
    }

    public void addEdge(int v, int w) {
        adj.get(v).add(w);
        adj.get(w).add(v);
    }

    public ArrayList<Integer> getAdj(int v) {
        return adj.get(v);
    }
}

次に、頂点 2 から幅優先トラバースを開始します。

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

public class BFS {
    public static void main(String[] args) {
        Graph g = new Graph(4);
        g.addEdge(2, 0);
        g.addEdge(2, 1);
        g.addEdge(2, 3);

        bfs(g, 2);
    }

    public static void bfs(Graph g, int s) {
        boolean[] visited = new boolean[g.V];
        Queue<Integer> queue = new LinkedList<>();

        visited[s] = true;
        queue.add(s);

        while (!queue.isEmpty()) {
            int v = queue.poll();
            System.out.print(v + " ");

            for (int w : g.getAdj(v)) {
                if (!visited[w]) {
                    visited[w] = true;
                    queue.add(w);
                }
            }
        }
    }
}

出力結果は次のとおりです: 2 0 1 3

これは、頂点 2 から開始する幅優先トラバースの結果です。

おすすめ

転載: blog.csdn.net/m0_62110645/article/details/129916908