delaunay/mst working
This commit is contained in:
60
util/kruskals/algorithm.go
Normal file
60
util/kruskals/algorithm.go
Normal 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
|
||||
}
|
47
util/kruskals/algorithm_test.gp.go
Normal file
47
util/kruskals/algorithm_test.gp.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user