ダイクストラアルゴリズム。最小優先度キューとしての最小ヒープ

マキシムドミトリエフ:

CLRS第3版p。662)のダイクストラのアルゴリズムについて読んでいます。これは私が理解できない本の一部です:

グラフが十分にまばらである場合、特に、E = o(V^2/lg V)バイナリの最小ヒープを持つ最小優先度キューを実装することで、アルゴリズムを改善できます。

なぜグラフを疎にする必要があるのですか?


ここに別の部分があります:

各DECREASE-KEY操作には時間がかかりますがO(log V)、そのような操作は最大でE個あります。

私のグラフが次のようになっているとします。

1から6

1から6までの最短経路を計算し、最小ヒープアプローチを使用したいと思います。まず、すべてのノードを最小優先度キューに追加します。最小ヒープを構築すると、最小ノードがソースノードになります(それ自体への距離が0であるため)。私はそれを抽出し、そのすべての隣人の距離を更新します。

次にdecreaseKey、ヒープの新しい最小値を作成するために、距離が最も短いノードを呼び出す必要があります。しかし、どのようにして一定の時間でそのインデックスを知ることができますか?

ノード

private static class Node implements Comparable<Node> {

    final int key;
    int distance = Integer.MAX_VALUE;
    Node prev = null;

    public Node(int key) {
        this.key = key;
    }

    @Override
    public int compareTo(Node o) {
        if (distance < o.distance) {
            return -1;
        } else if (distance > o.distance) {
            return 1;
        } else {
            return 0;
        }
    }

    @Override
    public String toString() {
        return "key=" + key + " distance=" + distance;
    }

    @Override
    public int hashCode() {
        return key;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Node)) {
            return false;
        }
        Node other = (Node) obj;
        return key == other.key;
    }
}

MinPriorityQueue

public static class MinPriorityQueue {

    private Node[] array;
    private int heapSize;

    public MinPriorityQueue(Node[] array) {
        this.array = array;
        this.heapSize = this.array.length;
    }

    public Node extractMin() {
        Node temp = array[0];
        swap(0, heapSize - 1, array);
        heapSize--;
        sink(0);
        return temp;
    }

    public boolean isEmpty() {
        return heapSize == 0;
    }

    public void buildMinHeap() {
        for (int i = heapSize / 2 - 1; i >= 0; i--) {
            sink(i);
        }
    }

    public void decreaseKey(int index, Node key) {
        if (key.compareTo(array[index]) >= 0) {
            throw new IllegalArgumentException("the new key must be greater than the current key");
        }
        array[index] = key;
        while (index > 0 && array[index].compareTo(array[parentIndex(index)]) < 0) {
            swap(index, parentIndex(index), array);
            index = parentIndex(index);
        }
    }

    private int parentIndex(int index) {
        return (index - 1) / 2;
    }

    private int left(int index) {
        return 2 * index + 1;
    }

    private int right(int index) {
        return 2 * index + 2;
    }

    private void sink(int index) {
        int smallestIndex = index;
        int left = left(index);
        int right = right(index);
        if (left < heapSize && array[left].compareTo(array[smallestIndex]) < 0) {
            smallestIndex = left;
        }
        if (right < heapSize && array[right].compareTo(array[smallestIndex]) < 0) {
            smallestIndex = right;
        }
        if (index != smallestIndex) {
            swap(smallestIndex, index, array);
            sink(smallestIndex);
        }
    }

    public Node min() {
        return array[0];
    }

    private void swap(int i, int j, Node[] array) {
        Node temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

}
夜:

なぜグラフを疎にする必要があるのですか?

ダイクストラのアルゴリズムの実行時間は、基になるデータ構造とグラフの形状(エッジと頂点)の組み合わせによって異なります。

たとえば、リンクリストを使用するにはO(V²)時間かかります。つまり、頂点の数にのみ依存します。ヒープを使用するにはO((V + E) log V)が必要です。つまり、頂点の数とエッジの数の両方に依存します。

EがVに比べて十分に小さい場合(のようにE << V² / logV)、ヒープの使用がより効率的になります。

次にdecreaseKey、ヒープの新しい最小値を作成するために、距離が最も短いノードを呼び出す必要があります。しかし、どのようにして一定の時間でそのインデックスを知ることができますか?

バイナリヒープを使用している場合、extractMin常にO(log V)時間内に実行され、距離が最も短いノード(キー)が表示されます。

たとえば、バイナリmin-heapを配列として実装している場合、配列Hの最初の要素H[1](慣例により、から数えます1)は常に最短距離の要素になるため、それを見つけるのに必要なのはだけO(1)です。

ただし、ごとにextractMininsertまたはdecreaseKey実行するswimsink、ヒープ状態を復元する必要があるため、結果として最短距離のノードが一番上に移動します。これはかかりますO(log V)

また、本で述べられているように、ヒープと頂点のキー間のマッピングを維持することもお勧めします。「頂点と対応するヒープ要素が互いにハンドルを維持していることを確認してください」(セクション6.5で簡単に説明)。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

隣接リストと優先度付きキューを使用したダイクストラのアルゴリズム

分類Dev

ダイクストラのアルゴリズム-隣接リストと最小ヒープ-java

分類Dev

優先キューとして半順序ツリーを使用したダイクストラの最短経路アルゴリズム

分類Dev

最大ヒープと最小ヒープの初期化(Java)優先度キュー

分類Dev

優先度キューとソートアルゴリズムのどちらかを決定する

分類Dev

このロジックは可能ですか?(懸念事項:バイナリ最小ヒープ、優先度キュー、インデックス0に挿入されますが、ルートはインデックス1にあります)

分類Dev

最小エッジのダイクストラのアルゴリズム

分類Dev

ダイクストラのアルゴリズムでキューとして使用するデータ型はどれですか?

分類Dev

Javaのダイクストラアルゴリズムはヒープスペースを使い果たしていますか?

分類Dev

STL最小ヒープ優先度キューを作成しますか?

分類Dev

ヒープ実装のためのダイクストラのアルゴリズムの複雑さ

分類Dev

ソースと宛先が同じ場合のダイクストラアルゴリズムの例

分類Dev

ダイクストラの最短経路アルゴリズム、C ++のヒープ実装

分類Dev

優先度でリソースを割り当てるアルゴリズム

分類Dev

優先度の高いユニセックスバスルームアルゴリズム

分類Dev

STL優先キューの説明を使用した最小ヒープ

分類Dev

ダイクストラアルゴリズムとJavaのソース変更

分類Dev

ダイクストラのアルゴリズム-無限ループ

分類Dev

優先距離キューとヒープを使用して最小距離を解決する方法

分類Dev

プロセスの終了時間を計算する方法は?-最小残余時間優先アルゴリズム

分類Dev

優先キューでのランダムアクセス

分類Dev

ユーザー定義オブジェクトを使用した最小優先度キュー(C ++ STL)の実装

分類Dev

確率的アルゴリズムとヒューリスティックアルゴリズムの違い

分類Dev

最小優先度キューと最大優先度キューが正しく並べ替えられない

分類Dev

Kargerの最小カットアルゴリズムでは、グラフの自己ループを排除します

分類Dev

ヒープベースの優先度キューを正しく実装していますか?ダウンヒープは必要ですか?

分類Dev

迷路のスペースをスキップする深さ優先探索アルゴリズム?

分類Dev

アルファ版のAPKアップロードに失敗しました。apksignerからのエラー:APIレベルでサポートされていないダイジェストアルゴリズムと署名アルゴリズム[[16、17]]

分類Dev

プログラムは、選択ソートアルゴリズムでリストの最小値を適切にソートしません

Related 関連記事

  1. 1

    隣接リストと優先度付きキューを使用したダイクストラのアルゴリズム

  2. 2

    ダイクストラのアルゴリズム-隣接リストと最小ヒープ-java

  3. 3

    優先キューとして半順序ツリーを使用したダイクストラの最短経路アルゴリズム

  4. 4

    最大ヒープと最小ヒープの初期化(Java)優先度キュー

  5. 5

    優先度キューとソートアルゴリズムのどちらかを決定する

  6. 6

    このロジックは可能ですか?(懸念事項:バイナリ最小ヒープ、優先度キュー、インデックス0に挿入されますが、ルートはインデックス1にあります)

  7. 7

    最小エッジのダイクストラのアルゴリズム

  8. 8

    ダイクストラのアルゴリズムでキューとして使用するデータ型はどれですか?

  9. 9

    Javaのダイクストラアルゴリズムはヒープスペースを使い果たしていますか?

  10. 10

    STL最小ヒープ優先度キューを作成しますか?

  11. 11

    ヒープ実装のためのダイクストラのアルゴリズムの複雑さ

  12. 12

    ソースと宛先が同じ場合のダイクストラアルゴリズムの例

  13. 13

    ダイクストラの最短経路アルゴリズム、C ++のヒープ実装

  14. 14

    優先度でリソースを割り当てるアルゴリズム

  15. 15

    優先度の高いユニセックスバスルームアルゴリズム

  16. 16

    STL優先キューの説明を使用した最小ヒープ

  17. 17

    ダイクストラアルゴリズムとJavaのソース変更

  18. 18

    ダイクストラのアルゴリズム-無限ループ

  19. 19

    優先距離キューとヒープを使用して最小距離を解決する方法

  20. 20

    プロセスの終了時間を計算する方法は?-最小残余時間優先アルゴリズム

  21. 21

    優先キューでのランダムアクセス

  22. 22

    ユーザー定義オブジェクトを使用した最小優先度キュー(C ++ STL)の実装

  23. 23

    確率的アルゴリズムとヒューリスティックアルゴリズムの違い

  24. 24

    最小優先度キューと最大優先度キューが正しく並べ替えられない

  25. 25

    Kargerの最小カットアルゴリズムでは、グラフの自己ループを排除します

  26. 26

    ヒープベースの優先度キューを正しく実装していますか?ダウンヒープは必要ですか?

  27. 27

    迷路のスペースをスキップする深さ優先探索アルゴリズム?

  28. 28

    アルファ版のAPKアップロードに失敗しました。apksignerからのエラー:APIレベルでサポートされていないダイジェストアルゴリズムと署名アルゴリズム[[16、17]]

  29. 29

    プログラムは、選択ソートアルゴリズムでリストの最小値を適切にソートしません

ホットタグ

アーカイブ