From 6f0a9042023b62787922f46baf222c86cb144ef8 Mon Sep 17 00:00:00 2001 From: Gourav Suri Date: Sat, 23 Oct 2021 02:43:40 +0530 Subject: [PATCH] added graph data structure --- Graph/Graph.go | 116 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 117 insertions(+) create mode 100644 Graph/Graph.go diff --git a/Graph/Graph.go b/Graph/Graph.go new file mode 100644 index 0000000..b99460b --- /dev/null +++ b/Graph/Graph.go @@ -0,0 +1,116 @@ +package Graph + +import ( +"errors" +"sync" +) + +var ( + // ErrVertexNotFound is returned when an operation is requested on a + // non-existent vertex. + ErrVertexNotFound = errors.New("vertex not found") + + // ErrSelfLoop is returned when an operation tries to create a disallowed + // self loop. + ErrSelfLoop = errors.New("self loops not permitted") + + // ErrParallelEdge is returned when an operation tries to create a + // disallowed parallel edge. + ErrParallelEdge = errors.New("parallel edges are not permitted") +) + +// SimpleGraph is a mutable, non-persistent undirected graph. +// Parallel edges and self-loops are not permitted. +// Additional description: https://en.wikipedia.org/wiki/Graph_(discrete_mathematics)#Simple_graph +type SimpleGraph struct { + mutex sync.RWMutex + adjacencyList map[interface{}]map[interface{}]struct{} + v, e int +} + +// V returns the number of vertices in the SimpleGraph +func (g *SimpleGraph) V() int { + g.mutex.RLock() + defer g.mutex.RUnlock() + + return g.v +} + +// E returns the number of edges in the SimpleGraph +func (g *SimpleGraph) E() int { + g.mutex.RLock() + defer g.mutex.RUnlock() + + return g.e +} + +// AddEdge will create an edge between vertices v and w +func (g *SimpleGraph) AddEdge(v, w interface{}) error { + g.mutex.Lock() + defer g.mutex.Unlock() + + if v == w { + return ErrSelfLoop + } + + g.addVertex(v) + g.addVertex(w) + + if _, ok := g.adjacencyList[v][w]; ok { + return ErrParallelEdge + } + + g.adjacencyList[v][w] = struct{}{} + g.adjacencyList[w][v] = struct{}{} + g.e++ + return nil +} + +// Adj returns the list of all vertices connected to v +func (g *SimpleGraph) Adj(v interface{}) ([]interface{}, error) { + g.mutex.RLock() + defer g.mutex.RUnlock() + + deg, err := g.Degree(v) + if err != nil { + return nil, ErrVertexNotFound + } + + adj := make([]interface{}, deg) + i := 0 + for key := range g.adjacencyList[v] { + adj[i] = key + i++ + } + return adj, nil +} + +// Degree returns the number of vertices connected to v +func (g *SimpleGraph) Degree(v interface{}) (int, error) { + g.mutex.RLock() + defer g.mutex.RUnlock() + + val, ok := g.adjacencyList[v] + if !ok { + return 0, ErrVertexNotFound + } + return len(val), nil +} + +func (g *SimpleGraph) addVertex(v interface{}) { + mm, ok := g.adjacencyList[v] + if !ok { + mm = make(map[interface{}]struct{}) + g.adjacencyList[v] = mm + g.v++ + } +} + +// NewSimpleGraph creates and returns a SimpleGraph +func NewSimpleGraph() *SimpleGraph { + return &SimpleGraph{ + adjacencyList: make(map[interface{}]map[interface{}]struct{}), + v: 0, + e: 0, + } +} \ No newline at end of file diff --git a/README.md b/README.md index 90c81b4..aeda8eb 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ There are several data structures and algorithms implemented in this project. Th - Binary Tree - Hash Table - Trie +- Graph ##### Searching algorithms - Linear Search