Last active
November 20, 2022 19:44
-
-
Save anisbhsl/4276d78fd8f7e287d9058395fd6c8132 to your computer and use it in GitHub Desktop.
Simple graph implementation (with BFS and DFS) in go using adj list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
) | |
type Graph struct{ | |
Nodes []*Node | |
} | |
//Node using adjacency list structure to represent the children with edges | |
type Node struct{ | |
Key int | |
Children []*Node | |
Visited bool //for search | |
} | |
//AddNode adds a node to the graph | |
func (g *Graph) AddNode(k int){ | |
if contains(g.Nodes,k){ | |
fmt.Printf("Node with key: '%v' already exists. So skipping the addition. \n", k) | |
return | |
} | |
g.Nodes=append(g.Nodes, &Node{ | |
Key: k, | |
}) | |
} | |
//Print method will print out all the nodes in graph with their children as adj list | |
func (g *Graph) Print(){ | |
for _, node := range g.Nodes{ | |
fmt.Printf("Key= %v ", node.Key) | |
for _, child := range node.Children{ | |
fmt.Printf("Child=> %v ", child.Key) | |
} | |
fmt.Printf("\n") | |
} | |
} | |
//checks whether the graph already has the node with given key | |
func contains(nodes []*Node, key int) bool{ | |
for _, node := range nodes{ | |
if key==node.Key{ | |
return true | |
} | |
} | |
return false | |
} | |
//getNode will retrieve node from graph along with its children | |
func (g *Graph) getNode(key int) *Node{ | |
for _, node := range g.Nodes{ | |
if node.Key==key{ | |
return node | |
} | |
} | |
return nil | |
} | |
//AddEdge will add edge/children of a node after checking it is really doesn't exist | |
func (g *Graph) AddEdge(from, to int){ | |
if !contains(g.Nodes,from){ | |
g.AddNode(from) | |
} | |
if !contains(g.Nodes, to){ | |
g.AddNode(to) | |
} | |
fromNode := g.getNode(from) | |
toNode := g.getNode(to) | |
if contains(fromNode.Children, to){ | |
fmt.Printf("Edge from key=> %v to key=> %v already exists \n", fromNode.Key, toNode.Key) | |
return | |
} | |
//add the children | |
fromNode.Children=append(fromNode.Children, toNode) | |
} | |
//BFSSearch performs Breadth First Search on the graph for given key | |
//I am implementing it as a traversal though for learning purposes | |
func (g *Graph) BFSSearch(key int) bool{ | |
fmt.Println("--Performing BFS Search--") | |
if len(g.Nodes)==0{ | |
return false | |
} | |
queue := g.Nodes | |
step:=0 | |
keyFound := false | |
visitedNodes := map[int]bool{} | |
queueLength := len(queue) | |
for queueLength!=0{ | |
for i, node := range queue{ | |
step++ | |
fmt.Printf("Traversing node with key: %v \n",node.Key) | |
if isVisited(visitedNodes, node.Key){ | |
continue | |
}else{ | |
visitedNodes[node.Key]=true | |
} | |
if node.Key==key{ | |
fmt.Printf("key found at search step: %v \n", step) | |
keyFound = true | |
} | |
if i+1<queueLength{ | |
queue = append(node.Children, queue[i+1:]...) | |
}else{ | |
queue=node.Children | |
} | |
queueLength=len(queue) | |
} | |
} | |
return keyFound | |
} | |
//DFSSearch performs Depth First Serach in a recursive fashion | |
func DFSSearch(node *Node, key int){ | |
if node==nil || node.Visited{ | |
return | |
} | |
fmt.Println("Traversing through the key: ", node.Key) | |
node.Visited=true | |
if node.Key==key{ | |
fmt.Println("Found the key: ", key) | |
} | |
for _, child := range node.Children{ | |
if child.Visited==false{ | |
DFSSearch(child,key) | |
} | |
} | |
} | |
func isVisited(visitedNodes map[int]bool, key int) bool{ | |
if visited, ok := visitedNodes[key]; ok && visited{ | |
return true | |
} | |
return false | |
} | |
func main() { | |
graph := &Graph{} | |
//add nodes | |
for i:=1;i<=7;i++{ | |
graph.AddNode(i) | |
} | |
//shouldn't allow to add 1 | |
graph.AddNode(1) | |
//add children | |
graph.AddEdge(1,2) | |
graph.AddEdge(1,3) | |
graph.AddEdge(2,4) | |
graph.AddEdge(2,5) | |
graph.AddEdge(3,6) | |
graph.AddEdge(3,7) | |
graph.AddEdge(3,7) | |
graph.Print() | |
graph.BFSSearch(3) | |
fmt.Println("--- DFS Search ---") | |
DFSSearch(graph.Nodes[0], 3) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Console output: