質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1334閲覧

ダイクストラ法 優先度付きキューについて

lime_penguins

総合スコア3

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2020/11/13 09:09

優先度付きキューを使ったダイクストラ法を学んでいるのですが、キューを作成したあたりから理解が追いつかず困っています。

python

1def min_heapify(data, i): 2 left = 2 * i + 1 3 right = 2 * i + 2 4 min = i 5 if left < len(data) and data[i][0] > data[left][0]: 6 min = left 7 if right < len(data) and data[min][0] > data[right][0]: 8 min = right 9 if min != i: 10 data[i], data[min] = data[min], data[i] 11 min_heapify(data, min) 12```ヒープソートで、先頭の要素を最も小さい値にする工程なのだと、ここまでは自分なりに理解ができました。 13```python 14def dijkstra(edges, num_v): 15 dist = [float('inf')] * num_v 16 dist[0] = 0 17 q = [[0, 0]] 18```各頂点に∞を入れて、最初の頂点までのコストは0にしている。 19キューを作成して[0, 0]を入れた。 20という認識です。 21 22```python 23 while len(q) > 0: 24 # キューから最小の要素を取り出し 25 q[0], q[-1] = q[-1], q[0] 26 _, u = q.pop() 27 # キューを再構成 28 min_heapify(q, 0) 29 # 各辺に対してコストを調べる 30 for i in edges[u]: 31 if dist[i[0]] > dist[u] + i[1]: 32 dist[i[0]] = dist[u] + i[1] 33 q.append([dist[u] + i[1], i[0]]) 34 j = len(q) - 1 35 while (j > 0) and (q[(j - 1) // 2] > q[j]): 36 q[(j - 1) // 2], q[j] = q[j], q[(j - 1) // 2] 37 j = (j - 1) // 2 38 39 return dist 40 41edges = [ 42 [[1, 4], [2, 3]], 43 [[2, 1], [3, 1], [4, 5]], 44 [[5, 2]], 45 [[4, 3]], 46 [[6, 2]], 47 [[4, 1], [6, 4]], 48 [] 49] 50print(dijkstra(edges, 7)) 51```ここからわからなくなってしまいました。 52qに何か数字が残っていた場合、キューから最小の要素を取り出し、各辺に対してコストを調べる、と書かれていますが、いまいち流れが掴めません。 53具体的な数字を入れて説明していただけると、大変ありがたいです。 54よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ockeghem

2020/11/13 09:27

なにを元に学んでいるのか出典を示してください
lime_penguins

2020/11/13 09:40

失礼致しました。 Pythonではじめるアルゴリズム入門 という本です。
guest

回答1

0

ベストアンサー

初期状態ではリストdistは、

dist: [0, inf, inf, inf, inf, inf, inf]

となっていますが、Aを起点に、A→Bのコストが4、A→Cのコストが3ですよね。Aから直接到達できるこれらを処理すると、

dist: [0, 4, 3, inf, inf, inf, inf]

となります。この段階でキューを示すリストqは空です。初期値 q = [[0, 0]] ですが、この値はループの先頭でpopしているからです。ここで、A→Bの距離4、A→Cの距離3をqにappendして、j = len(q) - 1 以下のwhileループでヒープ(q)を再構成しています(ここはちょっとスマートでないと思いました)。その結果、qは下記となります。

q: [[3, 2], [4, 1]]

リスト[3, 2]は、始点Aからの距離が3、地点がC(=2)ということです。同様に[4, 1]は、距離=4、地点=Bですね。qはヒープなので、距離最小値の[3, 2]が先頭にあります。
ダイクストラ法は、距離最小値の[3, 2]について処理をすればよいので、キューからこれをとりだし、残りをmin_heapifyします。
[3, 2]を取り出したことで、着眼点がC=2となりますので、Cからの距離を調べていきます。これは[5, 2]ですので、地点5(F)までの距離は3+2=5です。そこで、リストdistは下記になります。

dist: [0, 4, 3, inf, inf, 5, inf]

そして、qに距離5、地点5ということで、[5, 5]を追加します。qは下記となります。

q: [[4, 1], [5, 5]]

次の距離最小値点はB(=1)、距離は4ですので、同様の処理を地点Bに対して行います。以下同様となります。

投稿2020/11/14 09:41

ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lime_penguins

2020/11/15 06:56

ご回答ありがとうございます! 少々時間がかかってしまいましたが、しっかり理解することができました。 たしかに、whileループでヒープ(q)を再構成を再構成しているところは、無駄な経路があるように感じました。 なかなか一人では理解できなかったので、大変助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問