Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
A V program for Bellman-Ford's single source
|
||||
shortest path algorithm.
|
||||
literally adapted from:
|
||||
https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
|
||||
// Adapted from this site... from C++ and Python codes
|
||||
|
||||
For Portuguese reference
|
||||
http://rascunhointeligente.blogspot.com/2010/10/o-algoritmo-de-bellman-ford-um.html
|
||||
|
||||
code by CCS
|
||||
*/
|
||||
|
||||
const large = 999999 // almost infinity
|
||||
|
||||
// a structure to represent a weighted edge in graph
|
||||
struct EDGE {
|
||||
mut:
|
||||
src int
|
||||
dest int
|
||||
weight int
|
||||
}
|
||||
|
||||
// building a map of with all edges etc of a graph, represented from a matrix adjacency
|
||||
// Input: matrix adjacency --> Output: edges list of src, dest and weight
|
||||
fn build_map_edges_from_graph[T](g [][]T) map[T]EDGE {
|
||||
n := g.len // TOTAL OF NODES for this graph -- its dimensions
|
||||
mut edges_map := map[int]EDGE{} // a graph represented by map of edges
|
||||
|
||||
mut edge := 0 // a counter of edges
|
||||
for i in 0 .. n {
|
||||
for j in 0 .. n {
|
||||
// if exist an arc ... include as new edge
|
||||
if g[i][j] != 0 {
|
||||
edges_map[edge] = EDGE{i, j, g[i][j]}
|
||||
edge++
|
||||
}
|
||||
}
|
||||
}
|
||||
// print('${edges_map}')
|
||||
return edges_map
|
||||
}
|
||||
|
||||
fn print_sol(dist []int) {
|
||||
n_vertex := dist.len
|
||||
print('\n Vertex Distance from Source')
|
||||
for i in 0 .. n_vertex {
|
||||
print('\n ${i} --> ${dist[i]}')
|
||||
}
|
||||
}
|
||||
|
||||
// The main function that finds shortest distances from src
|
||||
// to all other vertices using Bellman-Ford algorithm. The
|
||||
// function also detects negative weight cycle
|
||||
fn bellman_ford[T](graph [][]T, src int) {
|
||||
mut edges := build_map_edges_from_graph[int](graph)
|
||||
// this function was done to adapt a graph representation
|
||||
// by a adjacency matrix, to list of adjacency (using a MAP)
|
||||
n_edges := edges.len // number of EDGES
|
||||
|
||||
// Step 1: Initialize distances from src to all other
|
||||
// vertices as INFINITE
|
||||
n_vertex := graph.len // adjc matrix ... n nodes or vertex
|
||||
mut dist := []int{len: n_vertex, init: large} // dist with -1 instead of INFINITY
|
||||
// mut path := []int{len: n , init:-1} // previous node of each shortest path
|
||||
dist[src] = 0
|
||||
|
||||
// Step 2: Relax all edges |V| - 1 times. A simple
|
||||
// shortest path from src to any other vertex can have
|
||||
// at-most |V| - 1 edges
|
||||
|
||||
for _ in 0 .. n_vertex {
|
||||
for j in 0 .. n_edges {
|
||||
mut u := edges[j].src
|
||||
mut v := edges[j].dest
|
||||
mut weight := edges[j].weight
|
||||
if dist[u] != large && dist[u] + weight < dist[v] {
|
||||
dist[v] = dist[u] + weight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: check for negative-weight cycles. The above
|
||||
// step guarantees shortest distances if graph doesn't
|
||||
// contain negative weight cycle. If we get a shorter
|
||||
// path, then there is a cycle.
|
||||
for j in 0 .. n_vertex {
|
||||
mut u := edges[j].src
|
||||
mut v := edges[j].dest
|
||||
mut weight := edges[j].weight
|
||||
if dist[u] != large && dist[u] + weight < dist[v] {
|
||||
print('\n Graph contains negative weight cycle')
|
||||
// If negative cycle is detected, simply
|
||||
// return or an exit(1)
|
||||
return
|
||||
}
|
||||
}
|
||||
print_sol(dist)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// adjacency matrix = cost or weight
|
||||
graph_01 := [
|
||||
[0, -1, 4, 0, 0],
|
||||
[0, 0, 3, 2, 2],
|
||||
[0, 0, 0, 0, 0],
|
||||
[0, 1, 5, 0, 0],
|
||||
[0, 0, 0, -3, 0],
|
||||
]
|
||||
// data from https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
|
||||
|
||||
graph_02 := [
|
||||
[0, 2, 0, 6, 0],
|
||||
[2, 0, 3, 8, 5],
|
||||
[0, 3, 0, 0, 7],
|
||||
[6, 8, 0, 0, 9],
|
||||
[0, 5, 7, 9, 0],
|
||||
]
|
||||
// data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
|
||||
/*
|
||||
The graph:
|
||||
2 3
|
||||
(0)--(1)--(2)
|
||||
| / \ |
|
||||
6| 8/ \5 |7
|
||||
| / \ |
|
||||
(3)-------(4)
|
||||
9
|
||||
*/
|
||||
|
||||
/*
|
||||
Let us create following weighted graph
|
||||
From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp
|
||||
10
|
||||
0--------1
|
||||
| \ |
|
||||
6| 5\ |15
|
||||
| \ |
|
||||
2--------3
|
||||
4
|
||||
*/
|
||||
graph_03 := [
|
||||
[0, 10, 6, 5],
|
||||
[10, 0, 0, 15],
|
||||
[6, 0, 0, 4],
|
||||
[5, 15, 4, 0],
|
||||
]
|
||||
|
||||
// To find number of columns
|
||||
// mut cols := an_array[0].len
|
||||
mut graph := [][]int{} // the graph: adjacency matrix
|
||||
// for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
graph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE
|
||||
// always starting by node 0
|
||||
start_node := 0
|
||||
println('\n\n Graph ${index + 1} using Bellman-Ford algorithm (source node: ${start_node})')
|
||||
bellman_ford(graph, start_node)
|
||||
}
|
||||
println('\n BYE -- OK')
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
fn main() {
|
||||
graph := {
|
||||
'A': ['B', 'C']
|
||||
'B': ['A', 'D', 'E']
|
||||
'C': ['A', 'F']
|
||||
'D': ['B']
|
||||
'E': ['B', 'F']
|
||||
'F': ['C', 'E']
|
||||
}
|
||||
println('Graph: ${graph}')
|
||||
path := breadth_first_search_path(graph, 'A', 'F')
|
||||
println('The shortest path from node A to node F is: ${path}')
|
||||
assert path == ['A', 'C', 'F']
|
||||
}
|
||||
|
||||
// Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph.
|
||||
fn breadth_first_search_path(graph map[string][]string, vertex string, target string) []string {
|
||||
mut path := []string{}
|
||||
mut visited := []string{len: 6, init: vertex}
|
||||
mut queue := [][][]string{}
|
||||
queue << [[vertex], path]
|
||||
for queue.len > 0 {
|
||||
mut idx := queue.len - 1
|
||||
node := queue[idx][0][0]
|
||||
path = queue[idx][1]
|
||||
queue.delete(idx)
|
||||
if node == target {
|
||||
path << node
|
||||
return path
|
||||
}
|
||||
for child in graph[node] {
|
||||
mut tmp := path.clone()
|
||||
if child !in visited {
|
||||
visited << child
|
||||
tmp << node
|
||||
queue << [[child], tmp]
|
||||
}
|
||||
}
|
||||
}
|
||||
return path
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Author: CCS
|
||||
// I follow literally code in C, done many years ago
|
||||
fn main() {
|
||||
// Adjacency matrix as a map
|
||||
graph := {
|
||||
'A': ['B', 'C']
|
||||
'B': ['A', 'D', 'E']
|
||||
'C': ['A', 'F']
|
||||
'D': ['B']
|
||||
'E': ['B', 'F']
|
||||
'F': ['C', 'E']
|
||||
}
|
||||
println('Graph: ${graph}')
|
||||
path := breadth_first_search_path(graph, 'A', 'F')
|
||||
println('\n The shortest path from node A to node F is: ${path.reverse()}')
|
||||
}
|
||||
|
||||
// Breadth-First Search (BFS) allows you to find the shortest distance between two nodes in the graph.
|
||||
fn breadth_first_search_path(graph map[string][]string, start string, target string) []string {
|
||||
mut path := []string{} // ONE PATH with SUCCESS = array
|
||||
mut queue := []string{} // a queue ... many paths
|
||||
// all_nodes := graph.keys() // get a key of this map
|
||||
// a map to store all the nodes visited to avoid cycles
|
||||
// start all them with False, not visited yet
|
||||
mut visited := visited_init(graph) // a map fully
|
||||
// false ==> not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}
|
||||
queue << start // first arrival
|
||||
for queue.len != 0 {
|
||||
mut node := departure(mut queue) // get the front node and remove it
|
||||
if visited[node] == false { // check if this node is already visited
|
||||
// if no ... test it searchinf for a final node
|
||||
visited[node] = true // means: visit this node
|
||||
if node == target {
|
||||
path = build_path_reverse(graph, start, node, visited)
|
||||
return path
|
||||
}
|
||||
// Expansion of node removed from queue
|
||||
print('\n Expansion of node ${node} (true/false): ${graph[node]}')
|
||||
// take all nodes from the node
|
||||
for vertex in graph[node] { // println("\n ...${vertex}")
|
||||
// not explored yet
|
||||
if visited[vertex] == false {
|
||||
queue << vertex
|
||||
}
|
||||
}
|
||||
print('\n QUEUE: ${queue} (only not visited) \n Visited: ${visited}')
|
||||
}
|
||||
}
|
||||
path = ['Path not found, problem in the Graph, start or end nodes! ']
|
||||
return path
|
||||
}
|
||||
|
||||
// classical removing of a node from the start of a queue
|
||||
fn departure(mut queue []string) string {
|
||||
mut x := queue[0]
|
||||
queue.delete(0)
|
||||
return x
|
||||
}
|
||||
|
||||
// Creating aa map to initialize with of visited nodes .... all with false in the init
|
||||
// so these nodes are NOT VISITED YET
|
||||
fn visited_init(a_graph map[string][]string) map[string]bool {
|
||||
mut temp := map[string]bool{} // attention in these initializations with maps
|
||||
for i, _ in a_graph {
|
||||
temp[i] = false
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// Based in the current node that is final, search for its parent, already visited, up to the root or start node
|
||||
fn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {
|
||||
print('\n\n Nodes visited (true) or no (false): ${visited}')
|
||||
array_of_nodes := graph.keys()
|
||||
mut current := final
|
||||
mut path := []string{}
|
||||
path << current
|
||||
|
||||
for (current != start) {
|
||||
for i in array_of_nodes {
|
||||
if current in graph[i] && visited[i] == true {
|
||||
current = i
|
||||
break // the first occurrence is enough
|
||||
}
|
||||
}
|
||||
path << current // update the path tracked
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
//======================================================
|
||||
@@ -0,0 +1,57 @@
|
||||
// Author: CCS & KeitoTobi1
|
||||
// Backtracking Supported.
|
||||
import datatypes
|
||||
|
||||
fn find_pattern(adj map[string][]string, start string, target string) [][]string {
|
||||
mut visited := visited_init(adj)
|
||||
mut queue := datatypes.Queue[[]string]{}
|
||||
mut res := [][]string{}
|
||||
queue.push([start])
|
||||
for !queue.is_empty() {
|
||||
mut v := queue.pop() or { panic(err) }
|
||||
node := v.last()
|
||||
if node == target {
|
||||
res << v
|
||||
}
|
||||
print('Expansion of node ${node} (true/false): ${adj[node]}')
|
||||
for next in adj[node] {
|
||||
if visited[next] == false {
|
||||
mut copy := v.clone()
|
||||
copy << next
|
||||
queue.push(copy)
|
||||
visited[node] = true
|
||||
}
|
||||
}
|
||||
print('Expansion of node ${queue} (true/false): ${visited}\n')
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fn print_pattern(pat [][]string) {
|
||||
for p in pat {
|
||||
println(p)
|
||||
}
|
||||
}
|
||||
|
||||
fn visited_init(adj map[string][]string) map[string]bool {
|
||||
mut temp := map[string]bool{}
|
||||
for i, _ in adj {
|
||||
temp[i] = false
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
fn main() {
|
||||
adj := {
|
||||
'A': ['B', 'C']
|
||||
'B': ['A', 'D', 'E']
|
||||
'C': ['A', 'F']
|
||||
'D': ['B']
|
||||
'E': ['B', 'F']
|
||||
'F': ['C', 'E']
|
||||
}
|
||||
|
||||
path := find_pattern(adj, 'A', 'F')
|
||||
println('The all pattern path from node A to node F is:')
|
||||
print_pattern(path)
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Author: CCS
|
||||
// I follow literally code in C, done many years ago
|
||||
|
||||
fn main() {
|
||||
// Adjacency matrix as a map
|
||||
// Example 01
|
||||
graph_01 := {
|
||||
'A': ['B', 'C']
|
||||
'B': ['A', 'D', 'E']
|
||||
'C': ['A', 'F']
|
||||
'D': ['B']
|
||||
'E': ['F', 'B', 'F']
|
||||
'F': ['C', 'E']
|
||||
}
|
||||
// Example 02
|
||||
graph_02 := {
|
||||
'A': ['B', 'C', 'D']
|
||||
'B': ['E']
|
||||
'C': ['F']
|
||||
'D': ['E']
|
||||
'E': ['H']
|
||||
'F': ['H']
|
||||
'G': ['H']
|
||||
'H': ['E', 'F', 'G']
|
||||
}
|
||||
path_01 := depth_first_search_path(graph_01, 'A', 'F')
|
||||
println('\n Graph_01: a first path from node A to node F is: ${path_01.reverse()}')
|
||||
path_02 := depth_first_search_path(graph_02, 'A', 'H')
|
||||
println('\n Graph_02: a first path from node A to node H is: ${path_02.reverse()}')
|
||||
}
|
||||
|
||||
// Depth-First Search (BFS) allows you to find a path between two nodes in the graph.
|
||||
fn depth_first_search_path(graph map[string][]string, start string, target string) []string {
|
||||
mut path := []string{} // ONE PATH with SUCCESS = array
|
||||
mut stack := []string{} // a stack ... many nodes
|
||||
// all_nodes := graph.keys() // get a key of this map
|
||||
mut visited := visited_init(graph) // a map fully with false in all vertex
|
||||
// false ... not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}
|
||||
|
||||
stack << start // first push on the stack
|
||||
for stack.len > 0 {
|
||||
mut node := stack.pop() // get the top node and remove it from the stack
|
||||
|
||||
// check if this node is already visited
|
||||
if visited[node] == false {
|
||||
// if no ... test it and search for a final node
|
||||
visited[node] = true // means: node visited
|
||||
if node == target {
|
||||
path = build_path_reverse(graph, start, node, visited)
|
||||
return path
|
||||
}
|
||||
// Exploring of node removed from stack and add its relatives
|
||||
print('\n Exploring of node ${node} (true/false): ${graph[node]}')
|
||||
// graph[node].reverse() take a classical choice for DFS
|
||||
// at most os left in this case.
|
||||
// use vertex in graph[node] the choice is right
|
||||
|
||||
// take all nodes from the node
|
||||
for vertex in graph[node].reverse() {
|
||||
// println("\n ...${vertex}")
|
||||
// not explored yet
|
||||
if visited[vertex] == false {
|
||||
stack << vertex
|
||||
}
|
||||
}
|
||||
print('\n Stack: ${stack} (only not visited) \n Visited: ${visited}')
|
||||
}
|
||||
}
|
||||
path = ['Path not found, problem in the Graph, start or end nodes! ']
|
||||
return path
|
||||
}
|
||||
|
||||
// Creating aa map to initialize with of visited nodes .... all with false in the init
|
||||
// so these nodes are NOT VISITED YET
|
||||
fn visited_init(a_graph map[string][]string) map[string]bool {
|
||||
mut temp := map[string]bool{} // attention in these initializations with maps
|
||||
for i, _ in a_graph {
|
||||
temp[i] = false
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// Based in the current node that is final, search for his parent, that is already visited, up to the root or start node
|
||||
fn build_path_reverse(graph map[string][]string, start string, final string, visited map[string]bool) []string {
|
||||
print('\n\n Nodes visited (true) or no (false): ${visited}')
|
||||
array_of_nodes := graph.keys()
|
||||
mut current := final
|
||||
mut path := []string{}
|
||||
path << current
|
||||
|
||||
for current != start {
|
||||
for i in array_of_nodes {
|
||||
if current in graph[i] && visited[i] == true {
|
||||
current = i
|
||||
break // the first occurrence is enough
|
||||
}
|
||||
}
|
||||
path << current // updating the path tracked
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
//*****************************************************
|
||||
@@ -0,0 +1,83 @@
|
||||
// Author: CCS & KeitoTobi1
|
||||
// Backtracking Supported.
|
||||
fn main() {
|
||||
// Adjacency matrix as a map
|
||||
// Example 01
|
||||
graph_01 := {
|
||||
'A': ['B', 'C']
|
||||
'B': ['A', 'D', 'E']
|
||||
'C': ['A', 'F']
|
||||
'D': ['B']
|
||||
'E': ['F', 'B', 'F']
|
||||
'F': ['C', 'E']
|
||||
}
|
||||
|
||||
// Example 02
|
||||
graph_02 := {
|
||||
'A': ['B', 'C', 'D']
|
||||
'B': ['E']
|
||||
'C': ['F']
|
||||
'D': ['E']
|
||||
'E': ['H']
|
||||
'F': ['H']
|
||||
'G': ['H']
|
||||
'H': ['E', 'F', 'G']
|
||||
}
|
||||
|
||||
path_01 := depth_first_search_path(graph_01, 'A', 'F')
|
||||
println('\n Graph_01: all path pattern from node A to node F is:')
|
||||
print_pattern(path_01)
|
||||
path_02 := depth_first_search_path(graph_02, 'A', 'H')
|
||||
println('\n Graph_02: all path pattern from node A to node F is:')
|
||||
print_pattern(path_02)
|
||||
}
|
||||
|
||||
fn depth_first_search_path(adj map[string][]string, start string, target string) [][]string {
|
||||
mut sol := Solution{}
|
||||
mut path := []string{}
|
||||
mut visited := visited_init(adj)
|
||||
|
||||
// false ... not visited yet: {'A': false, 'B': false, 'C': false, 'D': false, 'E': false}
|
||||
sol.find_pattern(adj, mut visited, start, target, mut path)
|
||||
return sol.pattern
|
||||
}
|
||||
|
||||
struct Solution {
|
||||
pub mut:
|
||||
pattern [][]string
|
||||
}
|
||||
|
||||
fn (mut s Solution) find_pattern(adj map[string][]string, mut visited map[string]bool, node string, target string,
|
||||
mut path []string) {
|
||||
path << node
|
||||
visited[node] = true
|
||||
if node == target {
|
||||
print('\n Founded pattern: ${path}')
|
||||
s.pattern << [path]
|
||||
}
|
||||
print('\n Exploring of node ${node} (true/false): ${adj[node]}')
|
||||
for i, _ in adj[node] {
|
||||
if !visited[adj[node][i]] {
|
||||
mut temp := path.clone()
|
||||
s.find_pattern(adj, mut visited, adj[node][i], target, mut temp)
|
||||
}
|
||||
}
|
||||
visited[node] = false
|
||||
print('\n Current: ${node} (only not visited) \n Visited: ${visited}')
|
||||
}
|
||||
|
||||
fn print_pattern(pat [][]string) {
|
||||
for p in pat {
|
||||
println(p)
|
||||
}
|
||||
}
|
||||
|
||||
// Creating aa map to initialize with of visited nodes .... all with false in the init
|
||||
// so these nodes are NOT VISITED YET
|
||||
fn visited_init(adj map[string][]string) map[string]bool {
|
||||
mut temp := map[string]bool{}
|
||||
for i, _ in adj {
|
||||
temp[i] = false
|
||||
}
|
||||
return temp
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
Exploring Dijkstra,
|
||||
The data example is from
|
||||
https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
|
||||
|
||||
by CCS
|
||||
Dijkstra's single source shortest path algorithm.
|
||||
The program uses an adjacency matrix representation of a graph
|
||||
|
||||
This Dijkstra algorithm uses a priority queue to save
|
||||
the shortest paths. The queue structure has a data
|
||||
which is the number of the node,
|
||||
and the priority field which is the shortest distance.
|
||||
|
||||
PS: all the pre-requisites of Dijkstra are considered
|
||||
|
||||
$ v run file_name.v
|
||||
// Creating a executable
|
||||
$ v run file_name.v -o an_executable.EXE
|
||||
$ ./an_executable.EXE
|
||||
|
||||
Code based from : Data Structures and Algorithms Made Easy: Data Structures and Algorithmic Puzzles, Fifth Edition (English Edition)
|
||||
pseudo code written in C
|
||||
This idea is quite different: it uses a priority queue to store the current
|
||||
shortest path evaluated
|
||||
The priority queue structure built using a list to simulate
|
||||
the queue. A heap is not used in this case.
|
||||
*/
|
||||
|
||||
// a structure
|
||||
struct NODE {
|
||||
mut:
|
||||
data int // NUMBER OF NODE
|
||||
priority int // Lower values priority indicate ==> higher priority
|
||||
}
|
||||
|
||||
// Function to push according to priority ... the lower priority is goes ahead
|
||||
// The "push" always sorted in pq
|
||||
fn push_pq[T](mut prior_queue []T, data int, priority int) {
|
||||
mut temp := []T{}
|
||||
pq_len := prior_queue.len
|
||||
|
||||
mut i := 0
|
||||
for i < pq_len && priority > prior_queue[i].priority {
|
||||
temp << prior_queue[i]
|
||||
i++
|
||||
}
|
||||
// INSERTING SORTED in the queue
|
||||
temp << NODE{data, priority} // do the copy in the right place
|
||||
// copy the another part (tail) of original prior_queue
|
||||
for i < pq_len {
|
||||
temp << prior_queue[i]
|
||||
i++
|
||||
}
|
||||
prior_queue = temp.clone() // I am not sure if it the right way
|
||||
// IS IT THE RIGHT WAY?
|
||||
}
|
||||
|
||||
// Change the priority of a value/node ... exist a value, change its priority
|
||||
fn updating_priority[T](mut prior_queue []T, search_data int, new_priority int) {
|
||||
mut i := 0
|
||||
mut pq_len := prior_queue.len
|
||||
|
||||
for i < pq_len {
|
||||
if search_data == prior_queue[i].data {
|
||||
prior_queue[i] = NODE{search_data, new_priority} // do the copy in the right place
|
||||
break
|
||||
}
|
||||
i++
|
||||
// all the list was examined
|
||||
if i >= pq_len {
|
||||
print('\n This data ${search_data} does exist ... PRIORITY QUEUE problem\n')
|
||||
exit(1) // panic(s string)
|
||||
}
|
||||
} // end for
|
||||
}
|
||||
|
||||
// a single departure or remove from queue
|
||||
fn departure_priority[T](mut prior_queue []T) int {
|
||||
mut x := prior_queue[0].data
|
||||
prior_queue.delete(0) // or .delete_many(0, 1 )
|
||||
return x
|
||||
}
|
||||
|
||||
// give a NODE v, return a list with all adjacents
|
||||
// Take care, only positive EDGES
|
||||
fn all_adjacents[T](g [][]T, v int) []int {
|
||||
mut temp := []int{}
|
||||
for i in 0 .. (g.len) {
|
||||
if g[v][i] > 0 {
|
||||
temp << i
|
||||
}
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// print the costs from origin up to all nodes
|
||||
fn print_solution[T](dist []T) {
|
||||
print('Vertex \tDistance from Source')
|
||||
for node in 0 .. (dist.len) {
|
||||
print('\n ${node} ==> \t ${dist[node]}')
|
||||
}
|
||||
}
|
||||
|
||||
// print all paths and their cost or weight
|
||||
fn print_paths_dist[T](path []T, dist []T) {
|
||||
print('\n Read the nodes from right to left (a path): \n')
|
||||
|
||||
for node in 1 .. (path.len) {
|
||||
print('\n ${node} ')
|
||||
mut i := node
|
||||
for path[i] != -1 {
|
||||
print(' <= ${path[i]} ')
|
||||
i = path[i]
|
||||
}
|
||||
print('\t PATH COST: ${dist[node]}')
|
||||
}
|
||||
}
|
||||
|
||||
// check structure from: https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
|
||||
// s: source for all nodes
|
||||
// Two results are obtained ... cost and paths
|
||||
fn dijkstra(g [][]int, s int) {
|
||||
mut pq_queue := []NODE{} // creating a priority queue
|
||||
push_pq(mut pq_queue, s, 0) // goes s with priority 0
|
||||
mut n := g.len
|
||||
|
||||
mut dist := []int{len: n, init: -1} // dist with -1 instead of INFINITE
|
||||
mut path := []int{len: n, init: -1} // previous node of each shortest path
|
||||
|
||||
// Distance of source vertex from itself is always 0
|
||||
dist[s] = 0
|
||||
|
||||
for pq_queue.len != 0 {
|
||||
mut v := departure_priority(mut pq_queue)
|
||||
// for all W adjacents vertices of v
|
||||
mut adjs_of_v := all_adjacents(g, v) // all_ADJ of v ....
|
||||
// print('\n ADJ ${v} is ${adjs_of_v}')
|
||||
mut new_dist := 0
|
||||
for w in adjs_of_v {
|
||||
new_dist = dist[v] + g[v][w]
|
||||
if dist[w] == -1 {
|
||||
dist[w] = new_dist
|
||||
push_pq(mut pq_queue, w, dist[w])
|
||||
path[w] = v // collecting the previous node -- lowest weight
|
||||
}
|
||||
if dist[w] > new_dist {
|
||||
dist[w] = new_dist
|
||||
updating_priority(mut pq_queue, w, dist[w])
|
||||
path[w] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print the constructed distance array
|
||||
print_solution(dist)
|
||||
// print('\n \n Previous node of shortest path: ${path}')
|
||||
print_paths_dist(path, dist)
|
||||
}
|
||||
|
||||
/*
|
||||
Solution Expected
|
||||
Vertex Distance from Source
|
||||
0 0
|
||||
1 4
|
||||
2 12
|
||||
3 19
|
||||
4 21
|
||||
5 11
|
||||
6 9
|
||||
7 8
|
||||
8 14
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
// adjacency matrix = cost or weight
|
||||
graph_01 := [
|
||||
[0, 4, 0, 0, 0, 0, 0, 8, 0],
|
||||
[4, 0, 8, 0, 0, 0, 0, 11, 0],
|
||||
[0, 8, 0, 7, 0, 4, 0, 0, 2],
|
||||
[0, 0, 7, 0, 9, 14, 0, 0, 0],
|
||||
[0, 0, 0, 9, 0, 10, 0, 0, 0],
|
||||
[0, 0, 4, 14, 10, 0, 2, 0, 0],
|
||||
[0, 0, 0, 0, 0, 2, 0, 1, 6],
|
||||
[8, 11, 0, 0, 0, 0, 1, 0, 7],
|
||||
[0, 0, 2, 0, 0, 0, 6, 7, 0],
|
||||
]
|
||||
|
||||
graph_02 := [
|
||||
[0, 2, 0, 6, 0],
|
||||
[2, 0, 3, 8, 5],
|
||||
[0, 3, 0, 0, 7],
|
||||
[6, 8, 0, 0, 9],
|
||||
[0, 5, 7, 9, 0],
|
||||
]
|
||||
// data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
|
||||
/*
|
||||
The graph:
|
||||
2 3
|
||||
(0)--(1)--(2)
|
||||
| / \ |
|
||||
6| 8/ \5 |7
|
||||
| / \ |
|
||||
(3)-------(4)
|
||||
9
|
||||
*/
|
||||
|
||||
/*
|
||||
Let us create following weighted graph
|
||||
From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp
|
||||
10
|
||||
0--------1
|
||||
| \ |
|
||||
6| 5\ |15
|
||||
| \ |
|
||||
2--------3
|
||||
4
|
||||
*/
|
||||
graph_03 := [
|
||||
[0, 10, 6, 5],
|
||||
[10, 0, 0, 15],
|
||||
[6, 0, 0, 4],
|
||||
[5, 15, 4, 0],
|
||||
]
|
||||
|
||||
// To find number of columns
|
||||
// mut cols := an_array[0].len
|
||||
mut graph := [][]int{} // the graph: adjacency matrix
|
||||
// for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
graph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE
|
||||
// always starting by node 0
|
||||
start_node := 0
|
||||
println('\n\n Graph ${index + 1} using Dijkstra algorithm (source node: ${start_node})')
|
||||
dijkstra(graph, start_node)
|
||||
}
|
||||
|
||||
println('\n BYE -- OK')
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
Exploring PRIMS,
|
||||
The data example is from
|
||||
https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
|
||||
|
||||
by CCS
|
||||
|
||||
PS: all the pre-requisites of Dijkstra are considered
|
||||
|
||||
$ v run file_name.v
|
||||
|
||||
Creating a executable
|
||||
$ v -o an_executable.EXE run file_name.v
|
||||
$ ./an_executable.EXE
|
||||
|
||||
Code based from : Data Structures and Algorithms Made Easy: Data Structures and Algorithmic Puzzles, Fifth Edition (English Edition)
|
||||
pseudo code written in C
|
||||
This idea is quite different: it uses a priority queue to store the current
|
||||
shortest path evaluated
|
||||
The priority queue structure built using a list to simulate
|
||||
the queue. A heap is not used in this case.
|
||||
*/
|
||||
|
||||
// a structure
|
||||
struct NODE {
|
||||
mut:
|
||||
data int // number of nodes
|
||||
priority int // Lower values priority indicate ==> higher priority
|
||||
}
|
||||
|
||||
// Function to push according to priority ... the lower priority is goes ahead
|
||||
// The "push" always sorted in pq
|
||||
fn push_pq[T](mut prior_queue []T, data int, priority int) {
|
||||
mut temp := []T{}
|
||||
pg_len := prior_queue.len
|
||||
|
||||
mut i := 0
|
||||
for i < pg_len && priority > prior_queue[i].priority {
|
||||
temp << prior_queue[i]
|
||||
i++
|
||||
}
|
||||
// INSERTING SORTED in the queue
|
||||
temp << NODE{data, priority} // do the copy in the right place
|
||||
// copy the another part (tail) of original prior_queue
|
||||
for i < pg_len {
|
||||
temp << prior_queue[i]
|
||||
i++
|
||||
}
|
||||
prior_queue = temp.clone() // I am not sure if it the right way
|
||||
}
|
||||
|
||||
// Change the priority of a value/node ... exist a value, change its priority
|
||||
fn updating_priority[T](mut prior_queue []T, search_data int, new_priority int) {
|
||||
mut i := 0
|
||||
mut pg_len := prior_queue.len
|
||||
|
||||
for i < pg_len {
|
||||
if search_data == prior_queue[i].data {
|
||||
prior_queue[i] = NODE{search_data, new_priority} // do the copy in the right place
|
||||
break
|
||||
}
|
||||
i++
|
||||
// all the list was examined
|
||||
if i >= pg_len {
|
||||
// print('\n Priority Queue: ${prior_queue}')
|
||||
// print('\n These data ${search_data} and ${new_priority} do not exist ... PRIORITY QUEUE problem\n')
|
||||
// if it does not find ... then push it
|
||||
push_pq(mut prior_queue, search_data, new_priority)
|
||||
// exit(1) // panic(s string)
|
||||
}
|
||||
} // end for
|
||||
}
|
||||
|
||||
// a single departure or remove from queue
|
||||
fn departure_priority[T](mut prior_queue []T) int {
|
||||
mut x := prior_queue[0].data
|
||||
prior_queue.delete(0) // or .delete_many(0, 1 )
|
||||
return x
|
||||
}
|
||||
|
||||
// give a NODE v, return a list with all adjacents
|
||||
// Take care, only positive EDGES
|
||||
fn all_adjacents[T](g [][]T, v int) []int {
|
||||
mut temp := []int{}
|
||||
for i in 0 .. (g.len) {
|
||||
if g[v][i] > 0 {
|
||||
temp << i
|
||||
}
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// print the costs from origin up to all nodes
|
||||
// A utility function to print the
|
||||
// constructed MST stored in parent[]
|
||||
// print all paths and their cost or weight
|
||||
fn print_solution(path []int, g [][]int) {
|
||||
// print(' PATH: ${path} ==> ${path.len}')
|
||||
print(' Edge \tWeight\n')
|
||||
mut sum := 0
|
||||
for node in 0 .. (path.len) {
|
||||
if path[node] == -1 {
|
||||
print('\n ${node} <== reference or start node')
|
||||
} else {
|
||||
print('\n ${node} <--> ${path[node]} \t${g[node][path[node]]}')
|
||||
sum += g[node][path[node]]
|
||||
}
|
||||
}
|
||||
print('\n Minimum Cost Spanning Tree: ${sum}\n\n')
|
||||
}
|
||||
|
||||
// check structure from: https://www.geeksforgeeks.org/dijkstras-shortest-path-algorithm-greedy-algo-7/
|
||||
// s: source for all nodes
|
||||
// Two results are obtained ... cost and paths
|
||||
fn prim_mst(g [][]int, s int) {
|
||||
mut pq_queue := []NODE{} // creating a priority queue
|
||||
push_pq(mut pq_queue, s, 0) // goes s with priority 0
|
||||
mut n := g.len
|
||||
|
||||
mut dist := []int{len: n, init: -1} // dist with -1 instead of INFINITE
|
||||
mut path := []int{len: n, init: -1} // previous node of each shortest path
|
||||
|
||||
// Distance of source vertex from itself is always 0
|
||||
dist[s] = 0
|
||||
|
||||
for pq_queue.len != 0 {
|
||||
mut v := departure_priority(mut pq_queue)
|
||||
// for all W adjacents vertices of v
|
||||
mut adjs_of_v := all_adjacents(g, v) // all_ADJ of v ....
|
||||
// print('\n :${dist} :: ${pq_queue}')
|
||||
// print('\n ADJ ${v} is ${adjs_of_v}')
|
||||
mut new_dist := 0
|
||||
for w in adjs_of_v {
|
||||
new_dist = dist[v] + g[v][w]
|
||||
|
||||
if dist[w] == -1 {
|
||||
dist[w] = g[v][w]
|
||||
push_pq(mut pq_queue, w, dist[w])
|
||||
path[w] = v // collecting the previous node -- lowest weight
|
||||
}
|
||||
|
||||
if dist[w] > new_dist {
|
||||
dist[w] = g[v][w] // new_dist//
|
||||
updating_priority(mut pq_queue, w, dist[w])
|
||||
path[w] = v // father / previous node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print('\n \n Previous node of shortest path: ${path}')
|
||||
// print_paths_dist(path , dist)
|
||||
print_solution(path, g)
|
||||
}
|
||||
|
||||
/*
|
||||
Solution Expected graph_02
|
||||
Edge Weight
|
||||
0 - 1 2
|
||||
1 - 2 3
|
||||
0 - 3 6
|
||||
1 - 4 5
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
// adjacency matrix = cost or weight
|
||||
graph_01 := [
|
||||
[0, 4, 0, 0, 0, 0, 0, 8, 0],
|
||||
[4, 0, 8, 0, 0, 0, 0, 11, 0],
|
||||
[0, 8, 0, 7, 0, 4, 0, 0, 2],
|
||||
[0, 0, 7, 0, 9, 14, 0, 0, 0],
|
||||
[0, 0, 0, 9, 0, 10, 0, 0, 0],
|
||||
[0, 0, 4, 14, 10, 0, 2, 0, 0],
|
||||
[0, 0, 0, 0, 0, 2, 0, 1, 6],
|
||||
[8, 11, 0, 0, 0, 0, 1, 0, 7],
|
||||
[0, 0, 2, 0, 0, 0, 6, 7, 0],
|
||||
]
|
||||
|
||||
graph_02 := [
|
||||
[0, 2, 0, 6, 0],
|
||||
[2, 0, 3, 8, 5],
|
||||
[0, 3, 0, 0, 7],
|
||||
[6, 8, 0, 0, 9],
|
||||
[0, 5, 7, 9, 0],
|
||||
]
|
||||
// data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
|
||||
/*
|
||||
The graph:
|
||||
2 3
|
||||
(0)--(1)--(2)
|
||||
| / \ |
|
||||
6| 8/ \5 |7
|
||||
| / \ |
|
||||
(3)-------(4)
|
||||
9
|
||||
Let us create following weighted graph
|
||||
From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp
|
||||
10
|
||||
0--------1
|
||||
| \ |
|
||||
6| 5\ |15
|
||||
| \ |
|
||||
2--------3
|
||||
4
|
||||
*/
|
||||
graph_03 := [
|
||||
[0, 10, 6, 5],
|
||||
[10, 0, 0, 15],
|
||||
[6, 0, 0, 4],
|
||||
[5, 15, 4, 0],
|
||||
]
|
||||
|
||||
// To find number of columns
|
||||
// mut cols := an_array[0].len
|
||||
mut graph := [][]int{} // the graph: adjacency matrix
|
||||
// for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
println('\n Minimal Spanning Tree of graph ${index + 1} using PRIM algorithm')
|
||||
graph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE
|
||||
// starting by node x ... see the graphs dimensions
|
||||
start_node := 0
|
||||
prim_mst(graph, start_node)
|
||||
}
|
||||
println('\n BYE -- OK')
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// https://en.wikipedia.org/wiki/Topological_sorting
|
||||
// A DFS RECURSIVE ALGORITHM ....
|
||||
// An alternative algorithm for topological sorting is based on depth-first search. The algorithm loops through each node of the graph, in an arbitrary order, initiating a depth-first search that terminates when it hits any node that has already been visited since the beginning
|
||||
// of the topological sort or the node has no outgoing edges (i.e. a leaf node)
|
||||
// Discussion: https://www.gatevidyalay.com/topological-sort-topological-sorting/
|
||||
// $ v run dfs_topological_ordering.v
|
||||
// Author: CCS
|
||||
|
||||
// THE DFS RECURSIVE .... classical searchig for leaves nodes
|
||||
// the arguments are used in the function to avoid global variables....
|
||||
fn dfs_recursive(u string, mut visited map[string]bool, graph map[string][]string, mut top_sorting []string) {
|
||||
print(' Visiting: ${u} -> ')
|
||||
visited[u] = true
|
||||
|
||||
for v in graph[u] {
|
||||
if visited[v] == false {
|
||||
dfs_recursive(v, mut visited, graph, mut top_sorting)
|
||||
}
|
||||
}
|
||||
top_sorting << u
|
||||
}
|
||||
|
||||
// Creating aa map to initialize with of visited nodes .... all with false in the init
|
||||
// so these nodes are NOT VISITED YET
|
||||
fn visited_init(a_graph map[string][]string) map[string]bool {
|
||||
mut array_of_keys := a_graph.keys() // get all keys of this map
|
||||
mut temp := map[string]bool{} // attention in these initializations with maps
|
||||
for i in array_of_keys {
|
||||
temp[i] = false
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
// attention here a map STRING ---> ONE BOOLEAN ... not a string
|
||||
|
||||
fn main() {
|
||||
// A map illustration to use in a graph
|
||||
// the graph: adjacency matrix
|
||||
graph_01 := {
|
||||
'A': ['C', 'B']
|
||||
'B': ['D']
|
||||
'C': ['D']
|
||||
'D': []
|
||||
}
|
||||
|
||||
graph_02 := {
|
||||
'A': ['B', 'C', 'D']
|
||||
'B': ['E']
|
||||
'C': ['F']
|
||||
'D': ['G']
|
||||
'E': ['H']
|
||||
'F': ['H']
|
||||
'G': ['H']
|
||||
'H': [] // no cycles
|
||||
}
|
||||
// from: https://en.wikipedia.org/wiki/Topological_sorting
|
||||
graph_03 := {
|
||||
'5': ['11']
|
||||
'7': ['11', '8']
|
||||
'3': ['8', '10']
|
||||
'11': ['2', '9', '10']
|
||||
'8': ['9']
|
||||
'2': []
|
||||
'9': []
|
||||
'10': []
|
||||
}
|
||||
|
||||
mut graph := map[string][]string{} // the graph: adjacency matrix
|
||||
for index, g_value in [graph_01, graph_02, graph_03] {
|
||||
println('Topological sorting for the graph ${index} using a DFS recursive')
|
||||
graph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE
|
||||
|
||||
// mut n_nodes := graph.len
|
||||
mut visited := visited_init(graph) // a map with nodes not visited
|
||||
|
||||
// mut start := (graph.keys()).first() // arbitrary, any node if you wish
|
||||
mut top_sorting := []string{}
|
||||
// advantages of map ... getting all nodes
|
||||
for i in graph.keys() {
|
||||
if visited[i] != true {
|
||||
dfs_recursive(i, mut visited, graph, mut top_sorting)
|
||||
}
|
||||
}
|
||||
|
||||
print('\n A topological sorting of graph ${index} : ')
|
||||
// println(g_value)
|
||||
println(top_sorting.reverse())
|
||||
println('')
|
||||
} // End of for
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
// The idea of this algorithm follow :
|
||||
// https://www.gatevidyalay.com/topological-sort-topological-sorting/ (GREEDY)
|
||||
// (no cycles are detected)
|
||||
// https://en.wikipedia.org/wiki/Topological_sorting ... just the input data
|
||||
// and the Kahn algorithm
|
||||
// Author: CCS
|
||||
|
||||
// the idea is rude: https://www.gatevidyalay.com/topological-sort-topological-sorting/
|
||||
fn topog_sort_greedy(graph map[string][]string) []string {
|
||||
n_nodes := graph.len // numbers of nodes of this graph
|
||||
mut top_order := []string{} // a vector with sequence of nodes visited
|
||||
mut count := 0
|
||||
/*
|
||||
IDEA ( a greedy algorithm ):
|
||||
|
||||
1. choose always the node with smallest input degree
|
||||
2. visit it
|
||||
3. put it in the output vector
|
||||
4. remove it from graph
|
||||
5. update the graph (a new graph)
|
||||
6. find a new vector degree
|
||||
7. until all nodes has been visited
|
||||
Back to step 1 (used the variable count)
|
||||
|
||||
Maybe it seems the Kahn's algorithm
|
||||
*/
|
||||
mut v_degree := in_degree(graph) // return: map [string] int
|
||||
print('V Degree ${v_degree}')
|
||||
mut small_degree := min_degree(v_degree)
|
||||
mut new_graph := remove_node_from_graph(small_degree, graph)
|
||||
top_order << small_degree
|
||||
count++
|
||||
|
||||
for (count < n_nodes) {
|
||||
v_degree = in_degree(new_graph) // return: map [string] int
|
||||
print('\nV Degree ${v_degree}')
|
||||
small_degree = min_degree(v_degree)
|
||||
new_graph = remove_node_from_graph(small_degree, new_graph)
|
||||
|
||||
top_order << small_degree
|
||||
count++
|
||||
}
|
||||
// print("\n New Graph ${new_graph}")
|
||||
|
||||
return top_order
|
||||
}
|
||||
|
||||
// Give a node, return a list with all nodes incidents or fathers of this node
|
||||
fn all_fathers(node string, a_map map[string][]string) []string {
|
||||
mut array_of_keys := a_map.keys() // get a key of this map
|
||||
mut all_incident := []string{}
|
||||
for i in array_of_keys {
|
||||
// in : function
|
||||
if node in a_map[i] {
|
||||
all_incident << i // a queue of this search
|
||||
}
|
||||
}
|
||||
return all_incident
|
||||
}
|
||||
|
||||
// Input: a map with input degree values, return the key with smallest value
|
||||
fn min_degree(a_map map[string]int) string {
|
||||
mut array_of_keys := a_map.keys() // get a key of this map
|
||||
mut key_min := array_of_keys.first()
|
||||
mut val_min := a_map[key_min]
|
||||
// print("\n MIN: ${val_min} \t key_min: ${key_min} \n the map inp_degree: ${a_map}")
|
||||
for i in array_of_keys {
|
||||
// there is a smaller
|
||||
if val_min > a_map[i] {
|
||||
val_min = a_map[i]
|
||||
key_min = i
|
||||
}
|
||||
}
|
||||
return key_min // the key with smallest value
|
||||
}
|
||||
|
||||
// Given a graph ... return a list of integer with degree of each node
|
||||
fn in_degree(a_map map[string][]string) map[string]int {
|
||||
mut array_of_keys := a_map.keys() // get a key of this map
|
||||
// print(array_of_keys)
|
||||
mut degree := map[string]int{}
|
||||
for i in array_of_keys {
|
||||
degree[i] = all_fathers(i, a_map).len
|
||||
}
|
||||
// print("\n Degree ${in_degree}" )
|
||||
return degree // a vector of the indegree graph
|
||||
}
|
||||
|
||||
// REMOVE A NODE FROM A GRAPH AND RETURN ANOTHER GRAPH
|
||||
fn remove_node_from_graph(node string, a_map map[string][]string) map[string][]string {
|
||||
// mut new_graph := map [string] string {}
|
||||
mut new_graph := a_map.clone() // copy the graph
|
||||
new_graph.delete(node)
|
||||
mut all_nodes := new_graph.keys() // get all nodes of this graph
|
||||
// FOR THE FUTURE with filter
|
||||
// for i in all_nodes {
|
||||
// new_graph[i] = new_graph[i].filter(index(it) != node)
|
||||
// }
|
||||
// A HELP FROM V discussion GITHUB - thread
|
||||
for key in all_nodes {
|
||||
i := new_graph[key].index(node)
|
||||
if i >= 0 {
|
||||
new_graph[key].delete(i)
|
||||
}
|
||||
}
|
||||
// print("\n NEW ${new_graph}" )
|
||||
return new_graph
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// A map illustration to use in a graph
|
||||
// adjacency matrix
|
||||
graph_01 := {
|
||||
'A': ['C', 'B']
|
||||
'B': ['D']
|
||||
'C': ['D']
|
||||
'D': []
|
||||
}
|
||||
|
||||
graph_02 := {
|
||||
'A': ['B', 'C', 'D']
|
||||
'B': ['E']
|
||||
'C': ['F']
|
||||
'D': ['G']
|
||||
'E': ['H']
|
||||
'F': ['H']
|
||||
'G': ['H']
|
||||
'H': []
|
||||
}
|
||||
// from: https://en.wikipedia.org/wiki/Topological_sorting
|
||||
graph_03 := {
|
||||
'5': ['11']
|
||||
'7': ['11', '8']
|
||||
'3': ['8', '10']
|
||||
'11': ['2', '9', '10']
|
||||
'8': ['9']
|
||||
'2': []
|
||||
'9': []
|
||||
'10': []
|
||||
}
|
||||
|
||||
println('\nA Topological Sort of G1: ${topog_sort_greedy(graph_01)}')
|
||||
println('\nA Topological Sort of G2: ${topog_sort_greedy(graph_02)}')
|
||||
println('\nA Topological Sort of G3: ${topog_sort_greedy(graph_03)}')
|
||||
// ['2', '9', '10', '11', '5', '8', '7', '3']
|
||||
}
|
||||
Reference in new issue
Block a user