v / examples / graphs / bfs2.v
90 lines · 84 sloc · 2.95 KB · 993546a0a2414a23fe0abf45d0c4f9b5dc31c1c1
Raw
1// Author: CCS
2// I follow literally code in C, done many years ago
3fn main() {
4 // Adjacency matrix as a map
5 graph := {
6 'A': ['B', 'C']
7 'B': ['A', 'D', 'E']
8 'C': ['A', 'F']
9 'D': ['B']
10 'E': ['B', 'F']
11 'F': ['C', 'E']
12 }
13 println('Graph: ${graph}')
14 path := breadth_first_search_path(graph, 'A', 'F')
15 println('\n The shortest path from node A to node F is: ${path.reverse()}')
16}
17
18// Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph.
19fn breadth_first_search_path(graph map[string][]string, start string, target string) []string {
20 mut path := []string{} // ONE PATH with SUCCESS = array
21 mut queue := []string{} // a queue ... many paths
22 // all_nodes := graph.keys() // get a key of this map
23 // a map to store all the nodes visited to avoid cycles
24 // start all them with False, not visited yet
25 mut visited := visited_init(graph) // a map fully
26 // false ==> not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}
27 queue << start // first arrival
28 for queue.len != 0 {
29 mut node := departure(mut queue) // get the front node and remove it
30 if visited[node] == false { // check if this node is already visited
31 // if no ... test it searchinf for a final node
32 visited[node] = true // means: visit this node
33 if node == target {
34 path = build_path_reverse(graph, start, node, visited)
35 return path
36 }
37 // Expansion of node removed from queue
38 print('\n Expansion of node ${node} (true/false): ${graph[node]}')
39 // take all nodes from the node
40 for vertex in graph[node] { // println("\n ...${vertex}")
41 // not explored yet
42 if visited[vertex] == false {
43 queue << vertex
44 }
45 }
46 print('\n QUEUE: ${queue} (only not visited) \n Visited: ${visited}')
47 }
48 }
49 path = ['Path not found, problem in the Graph, start or end nodes! ']
50 return path
51}
52
53// classical removing of a node from the start of a queue
54fn departure(mut queue []string) string {
55 mut x := queue[0]
56 queue.delete(0)
57 return x
58}
59
60// Creating aa map to initialize with of visited nodes .... all with false in the init
61// so these nodes are NOT VISITED YET
62fn visited_init(a_graph map[string][]string) map[string]bool {
63 mut temp := map[string]bool{} // attention in these initializations with maps
64 for i, _ in a_graph {
65 temp[i] = false
66 }
67 return temp
68}
69
70// Based in the current node that is final, search for its parent, already visited, up to the root or start node
71fn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {
72 print('\n\n Nodes visited (true) or no (false): ${visited}')
73 array_of_nodes := graph.keys()
74 mut current := final
75 mut path := []string{}
76 path << current
77
78 for (current != start) {
79 for i in array_of_nodes {
80 if current in graph[i] && visited[i] == true {
81 current = i
82 break // the first occurrence is enough
83 }
84 }
85 path << current // update the path tracked
86 }
87 return path
88}
89
90//======================================================
91