mirror of https://github.com/emirpasic/gods
add feature directed and undirected graph
parent
79df803e55
commit
da08a10525
@ -0,0 +1,119 @@
|
||||
package graphs
|
||||
|
||||
// Graph holds vertices and edges of a graph
|
||||
type Graph struct {
|
||||
isDirected bool
|
||||
vertices []node
|
||||
}
|
||||
|
||||
type node struct {
|
||||
name interface{}
|
||||
edges []interface{}
|
||||
}
|
||||
|
||||
const infinity = int(^uint(0) >> 1)
|
||||
|
||||
// NewDirectedGraph is for creating a directed graph
|
||||
func NewDirectedGraph() *Graph {
|
||||
g := Graph{}
|
||||
g.vertices = make([]node, 0)
|
||||
g.isDirected = true
|
||||
return &g
|
||||
}
|
||||
|
||||
// NewUndirectedGraph is for creating an undirected graph
|
||||
func NewUndirectedGraph() *Graph {
|
||||
g := Graph{}
|
||||
g.vertices = make([]node, 0)
|
||||
g.isDirected = false
|
||||
return &g
|
||||
}
|
||||
|
||||
// AddVertice is for adding a new vertice. id vertice exists do nothing
|
||||
func (g *Graph) AddVertice(name interface{}) {
|
||||
g.addVertice(name)
|
||||
}
|
||||
|
||||
// AddEdge if for adding a new edge.
|
||||
func (g *Graph) AddEdge(from, to interface{}) {
|
||||
g.addEdge(from, to)
|
||||
}
|
||||
|
||||
// GetEdge is for getting all the edges of vertice n
|
||||
func (g *Graph) GetEdge(n interface{}) []interface{} {
|
||||
return g.getEdge(n)
|
||||
}
|
||||
|
||||
// GetVertices is for getting all vertices info
|
||||
func (g *Graph) GetVertices() []interface{} {
|
||||
return g.getVertices()
|
||||
}
|
||||
|
||||
// ShortestPath is for finding shortest path from edge s to t by using belman-ford algorithm
|
||||
func (g *Graph) ShortestPath(s, t interface{}) map[interface{}]int {
|
||||
return g.shortestPath(s, t)
|
||||
}
|
||||
|
||||
func (g *Graph) addVertice(name interface{}) int {
|
||||
for i, v := range g.vertices {
|
||||
if v.name == name {
|
||||
return i
|
||||
}
|
||||
}
|
||||
n := node{}
|
||||
n.name = name
|
||||
n.edges = make([]interface{}, 0)
|
||||
g.vertices = append(g.vertices, n)
|
||||
|
||||
return len(g.vertices) - 1
|
||||
}
|
||||
|
||||
func (g *Graph) addEdge(from, to interface{}) {
|
||||
f := g.addVertice(from)
|
||||
t := g.addVertice(to)
|
||||
g.vertices[f].edges = append(g.vertices[f].edges, to)
|
||||
if !g.isDirected {
|
||||
g.vertices[t].edges = append(g.vertices[t].edges, from)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Graph) getEdge(n interface{}) []interface{} {
|
||||
for _, v := range g.vertices {
|
||||
if v.name == n {
|
||||
return v.edges
|
||||
}
|
||||
}
|
||||
// todo throw exception
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Graph) getVertices() []interface{} {
|
||||
vertices := make([]interface{}, 0)
|
||||
for i := 0; i < len(g.vertices); i++ {
|
||||
vertices = append(vertices, g.vertices[i].name)
|
||||
}
|
||||
return vertices
|
||||
}
|
||||
|
||||
func (g *Graph) shortestPath(sName, tName interface{}) map[interface{}]int {
|
||||
n := len(g.vertices)
|
||||
s := g.addVertice(sName)
|
||||
dist := make([]int, n)
|
||||
for i := 0; i < n; i++ {
|
||||
dist[i] = infinity
|
||||
}
|
||||
dist[s] = 0
|
||||
for u := 0; u < n-1; u++ {
|
||||
for _, vName := range g.vertices[u].edges {
|
||||
v := g.addVertice(vName)
|
||||
if dist[u] != infinity && dist[u]+1 < dist[v] {
|
||||
dist[v] = dist[u] + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
result := make(map[interface{}]int)
|
||||
for i, d := range dist {
|
||||
result[g.vertices[i].name] = d
|
||||
}
|
||||
return result
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package graphs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGrsphAddVertice(t *testing.T) {
|
||||
g1 := NewDirectedGraph()
|
||||
g1.AddVertice("a")
|
||||
g1.AddVertice("b")
|
||||
g1.AddVertice("c")
|
||||
g1.AddVertice("d")
|
||||
actualValue1 := g1.GetVertices()
|
||||
expectedValue1 := []string{"a", "b", "c", "d"}
|
||||
for i, v := range expectedValue1 {
|
||||
if v != actualValue1[i] {
|
||||
t.Errorf("Got %v expected %v", actualValue1, expectedValue1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
g2 := NewDirectedGraph()
|
||||
g2.AddVertice(1)
|
||||
g2.AddVertice(2)
|
||||
g2.AddVertice(3)
|
||||
g2.AddVertice(4)
|
||||
actualValue2 := g2.GetVertices()
|
||||
|
||||
expectedValue2 := []int{1, 2, 3, 4}
|
||||
for i, v := range expectedValue2 {
|
||||
if v != actualValue2[i] {
|
||||
t.Errorf("Got %v expected %v", actualValue2, expectedValue2)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
g3 := NewUndirectedGraph()
|
||||
g3.AddVertice("a")
|
||||
g3.AddVertice("b")
|
||||
g3.AddVertice("c")
|
||||
g3.AddVertice("d")
|
||||
actualValue3 := g3.GetVertices()
|
||||
expectedValue3 := []string{"a", "b", "c", "d"}
|
||||
for i, v := range expectedValue3 {
|
||||
if v != actualValue3[i] {
|
||||
t.Errorf("Got %v expected %v", actualValue3, expectedValue3)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGrsphAddEdge(t *testing.T) {
|
||||
g1 := NewDirectedGraph()
|
||||
g1.AddVertice("a")
|
||||
g1.AddVertice("b")
|
||||
g1.AddEdge("a", "b")
|
||||
g1.AddEdge("c", "a")
|
||||
actualValue1 := g1.GetEdge("a")
|
||||
expectedValue1 := []string{"b"}
|
||||
for i, v := range expectedValue1 {
|
||||
if v != actualValue1[i] {
|
||||
t.Errorf("Got %v expected %v", actualValue1, expectedValue1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
g2 := NewUndirectedGraph()
|
||||
g2.AddVertice("a")
|
||||
g2.AddVertice("b")
|
||||
g2.AddEdge("a", "b")
|
||||
g2.AddEdge("c", "a")
|
||||
actualValue2 := g2.GetEdge("a")
|
||||
expectedValue2 := []string{"b", "c"}
|
||||
for i, v := range expectedValue2 {
|
||||
if v != actualValue2[i] {
|
||||
t.Errorf("Got %v expected %v", actualValue2, expectedValue2)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortestPath(t *testing.T) {
|
||||
g := NewDirectedGraph()
|
||||
g.addEdge("a", "b")
|
||||
g.addEdge("b", "c")
|
||||
g.addEdge("c", "a")
|
||||
g.addEdge("c", "d")
|
||||
|
||||
tests := [][]interface{}{
|
||||
{1, "a", 0},
|
||||
{2, "b", 1},
|
||||
{3, "c", 2},
|
||||
{4, "d", 3},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
actualValue, expectedValue := g.shortestPath("a", "b")[test[1]], test[2]
|
||||
if actualValue != expectedValue {
|
||||
t.Errorf("Got %v expected %v", actualValue, expectedValue)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue