囲碁におけるヒープを用いたダイクストラの実装
囲碁でヒープを使用してダイクストラの簡単な実装。
ダイクストラとは何か
メガ短い説明:ダイクストラのアルゴリズムは、AとBの間の最短パスを見つけるために、それは、最も遠い距離で未訪問のノードを選択し、それぞれの訪問していない隣人にそれを介して距離を計算し、より小さい場合は、隣人の距離を更新します.
ヒープは何ですか。
コンピュータ科学において、ヒープは基本的にヒーププロパティを満たすほとんど完全な木です:最大のヒープでは、どんな与えられたノードCのためにでも、PがCの親ノードであるならば、Pのキー(値)はCのキーより大きいか、Cのキーに等しいです.PのキーはCのキー以下である.ヒープの“top”(親なし)のノードはルートノードと呼ばれる.
Wikipedia
ヒープは、優先順位キューとして考えることができます最も重要なノードは常に上部にあり、削除されると、その置換が最も重要になります.これは、完全な順序で処理する特定のものを必要とするアルゴリズムをコーディングするときに便利です.しかし、完全なソートを実行したくない場合や、ノードの残りの部分について何かを知る必要がない場合.例えば、グラフの中でノード間の最短距離を見つけるためのよく知られたアルゴリズム、ダイクストラのアルゴリズムは、優先順位キューを使用して最適化することができます.
Cprogramming
なぜ?
私はグラフとそのアルゴリズムについて学ぶことを試みているので、私は大学に行ったことがないので、私はグラフについてあまり知らないので、私は私の自由な時間の中でこれを読んで、それを学ぶしようとするため、私は最近、ヒープを使用してPythonでダイクストラの1つの実装についてのビデオを見て面白かったので、私は同じことを行うことを決めた.
私は同じトピックについて多くの記事があります、そして、これらの記事が非常によくdijkstraまたは何がヒープであるかについて説明するということを知っていて、この記事は単に実装に集中する短い記事であるでしょう、私はあなたにゴングでヒープを使用しているダイクストラの非常に単純な実装を示したいです.
あなたがDjkstraについてもっと読みたいならば、あなたが私が見つけたこの記事を読むべきであることは驚くべきです.
An excelenct article
実装
ダイクストラは、2つのノード間の短いパスを探索するアルゴリズムであり、各ノードの隣人を訪問し、常に最小値を保っている原点ノードからのコストとパスを計算するアルゴリズムである.
まず、Min Hapを実装する必要があります.
パッケージヒープはヒープを実装する任意の型のヒープ操作を提供します.インターフェイス.ヒープは、各ノードがそのサブツリー内の最小値ノードであるプロパティを持つツリーです.
Godoc - heap
ヒープ.試み
package main
import hp "container/heap"
type path struct {
value int
nodes []string
}
type minPath []path
func (h minPath) Len() int { return len(h) }
func (h minPath) Less(i, j int) bool { return h[i].value < h[j].value }
func (h minPath) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *minPath) Push(x interface{}) {
*h = append(*h, x.(path))
}
func (h *minPath) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
type heap struct {
values *minPath
}
func newHeap() *heap {
return &heap{values: &minPath{}}
}
func (h *heap) push(p path) {
hp.Push(h.values, p)
}
func (h *heap) pop() path {
i := hp.Pop(h.values)
return i.(path)
}
第二に、我々はグラフのロジックを実装する必要があるため、我々は、エッジを追加し、1つのノードからすべてのエッジを取得する機能を持つノード間のエッジを保つためにマップを含む構造体を使用する必要があります.関数GetPathはダイジェクストラアルゴリズムを実装し、原点と運命の最短パスを取得します.
グラフ.試み
package main
type edge struct {
node string
weight int
}
type graph struct {
nodes map[string][]edge
}
func newGraph() *graph {
return &graph{nodes: make(map[string][]edge)}
}
func (g *graph) addEdge(origin, destiny string, weight int) {
g.nodes[origin] = append(g.nodes[origin], edge{node: destiny, weight: weight})
g.nodes[destiny] = append(g.nodes[destiny], edge{node: origin, weight: weight})
}
func (g *graph) getEdges(node string) []edge {
return g.nodes[node]
}
func (g *graph) getPath(origin, destiny string) (int, []string) {
h := newHeap()
h.push(path{value: 0, nodes: []string{origin}})
visited := make(map[string]bool)
for len(*h.values) > 0 {
// Find the nearest yet to visit node
p := h.pop()
node := p.nodes[len(p.nodes)-1]
if visited[node] {
continue
}
if node == destiny {
return p.value, p.nodes
}
for _, e := range g.getEdges(node) {
if !visited[e.node] {
// We calculate the total spent so far plus the cost and the path of getting here
h.push(path{value: p.value + e.weight, nodes: append([]string{}, append(p.nodes, e.node)...)})
}
}
visited[node] = true
}
return 0, nil
}
メイン.試みpackage main
import (
"fmt"
)
func main() {
fmt.Println("Dijkstra")
// Example
graph := newGraph()
graph.addEdge("S", "B", 4)
graph.addEdge("S", "C", 2)
graph.addEdge("B", "C", 1)
graph.addEdge("B", "D", 5)
graph.addEdge("C", "D", 8)
graph.addEdge("C", "E", 10)
graph.addEdge("D", "E", 2)
graph.addEdge("D", "T", 6)
graph.addEdge("E", "T", 2)
fmt.Println(graph.getPath("S", "T"))
}
$ go run .
Dijkstra
12 [S C B D E T]
GithubReference
この問題について(囲碁におけるヒープを用いたダイクストラの実装), 我々は、より多くの情報をここで見つけました https://dev.to/douglasmakey/implementation-of-dijkstra-using-heap-in-go-6e3テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol