delaunay/mst working

This commit is contained in:
2019-11-13 02:56:09 +03:00
parent f55549a048
commit d7b24d5abc
17 changed files with 589 additions and 40 deletions

View File

@ -0,0 +1,60 @@
package kruskals
import (
"lab.zaar.be/thefish/alchemyst-go/util/uf"
"sort"
)
// WeightedEdge is an undirected edge between vertices and a weight.
type WeightedEdge interface {
// From returns the integer identifier of the first vertex.
From() int
// To returns the integer identifier of the second vertex.
To() int
// Weight returns the integer identifier of the weight/cost.
Weight() int
}
// SimpleWeightedEdge is a simple implementation of the interface.
// Initialize with 'F' (From), 'T' (To), 'W' (Weight).
type SimpleWeightedEdge struct {
F, T, W int
}
// From returns the integer identifier of the first vertex.
func (s SimpleWeightedEdge) From() int {
return s.F
}
// To returns the integer identifier of the second vertex.
func (s SimpleWeightedEdge) To() int {
return s.T
}
// Weight returns the integer identifier of the weight/cost.
func (s SimpleWeightedEdge) Weight() int {
return s.W
}
// MinimumSpanningTree returns the fewest edges to span across the graph
// with the minimum cost based on weights.
func MinimumSpanningTree(edges []WeightedEdge) []WeightedEdge {
vertices := make(map[int]struct{})
for _, e := range edges {
vertices[e.From()] = struct{}{}
vertices[e.To()] = struct{}{}
}
sort.Slice(edges, func(i, j int) bool {
return edges[i].Weight() < edges[j].Weight()
})
u := uf.New(len(vertices))
result := make([]WeightedEdge, 0, len(edges))
for _, e := range edges {
if !u.Connected(e.From(), e.To()) {
u.Union(e.From(), e.To())
result = append(result, e)
}
}
return result
}

View File

@ -0,0 +1,47 @@
package kruskals
import (
"reflect"
"testing"
)
var testcases = []struct {
graph, mst []WeightedEdge
}{
{
[]WeightedEdge{
SimpleWeightedEdge{0, 3, 3},
SimpleWeightedEdge{3, 1, 30},
SimpleWeightedEdge{0, 1, 20},
SimpleWeightedEdge{0, 4, 10},
SimpleWeightedEdge{1, 4, 5},
SimpleWeightedEdge{4, 2, 20},
SimpleWeightedEdge{1, 2, 50},
SimpleWeightedEdge{3, 0, 3},
},
[]WeightedEdge{
SimpleWeightedEdge{0, 3, 3},
SimpleWeightedEdge{1, 4, 5},
SimpleWeightedEdge{0, 4, 10},
SimpleWeightedEdge{4, 2, 20},
},
},
}
func TestMinimumSpanningTree(t *testing.T) {
t.Parallel()
for _, tc := range testcases {
if result := MinimumSpanningTree(tc.graph); !reflect.DeepEqual(result, tc.mst) {
t.Errorf("Expected %v, got %v", tc.mst, result)
}
}
}
func BenchmarkMinimumSpanningTree(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testcases {
MinimumSpanningTree(tc.graph)
}
}
}