Skip to content

Instantly share code, notes, and snippets.

@anisbhsl
Last active November 20, 2022 19:44
Show Gist options
  • Save anisbhsl/4276d78fd8f7e287d9058395fd6c8132 to your computer and use it in GitHub Desktop.
Save anisbhsl/4276d78fd8f7e287d9058395fd6c8132 to your computer and use it in GitHub Desktop.
Simple graph implementation (with BFS and DFS) in go using adj list
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)
}
@anisbhsl
Copy link
Author

anisbhsl commented Nov 20, 2022

Console output:

Node with key: '1' already exists. So skipping the addition. 
Edge from key=> 3 to key=> 7 already exists 
Key= 1 Child=> 2 Child=> 3 
Key= 2 Child=> 4 Child=> 5 
Key= 3 Child=> 6 Child=> 7 
Key= 4 
Key= 5 
Key= 6 
Key= 7 
--Performing BFS Search--
Traversing node with key: 1 
Traversing node with key: 2 
Traversing node with key: 3 
key found at search step: 3 
Traversing node with key: 4 
Traversing node with key: 5 
Traversing node with key: 6 
Traversing node with key: 7 
--- DFS Search ---
Traversing through the key:  1
Traversing through the key:  2
Traversing through the key:  4
Traversing through the key:  5
Traversing through the key:  3
Traversing through the key:  6
Traversing through the key:  7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment