Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementend algorithm in different languages C, Rust, Go #24

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dijkstras.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,4 @@ public List<Character> getShortestPath(Character start, Character finish) {
return new ArrayList<Character>(distances.keySet());
}

}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ Each example should feature this graph and should print the path A->B->F->H in s
ex. `py dijkstras.py` >>> \['H', 'F', 'B'\]

## Current Supported Languages:
C++, C#, Java, Javascript, Typescript, Coffeescript, PHP, **Python**, **Ruby**, Scala
C++, C#, Java, Javascript, Typescript, Coffeescript, PHP, **Python**, **Ruby**, Scala, C, Go, Rust
*(Bolded languages have associated test-suites)*
86 changes: 86 additions & 0 deletions dijkstra.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define MAX_NODES 1000

struct Edge {
int to;
int cost;
};

struct Node {
int id;
int dist;
};

int cmp(const void *a, const void *b) {
const struct Node *node_a = (const struct Node *)a;
const struct Node *node_b = (const struct Node *)b;
return node_b->dist - node_a->dist;
}

void dijkstra(struct Edge **nodes, int num_nodes, int start, int *dist) {
int i, j;
struct Node pq[MAX_NODES];
int pq_size = 0;

for (i = 0; i < num_nodes; i++) {
dist[i] = INT_MAX;
}
dist[start] = 0;

pq[pq_size++] = (struct Node){ start, 0 };
qsort(pq, pq_size, sizeof(struct Node), cmp);

while (pq_size > 0) {
struct Node node = pq[--pq_size];

for (j = 0; j < num_nodes; j++) {
if (nodes[node.id][j].to < 0) break;

int new_dist = dist[node.id] + nodes[node.id][j].cost;
if (new_dist < dist[nodes[node.id][j].to]) {
dist[nodes[node.id][j].to] = new_dist;
pq[pq_size++] = (struct Node){ nodes[node.id][j].to, new_dist };
qsort(pq, pq_size, sizeof(struct Node), cmp);
}
}
}
}

int main() {
int num_nodes = 4;
struct Edge **nodes = (struct Edge **)malloc(num_nodes * sizeof(struct Edge *));
int i, j;

for (i = 0; i < num_nodes; i++) {
nodes[i] = (struct Edge *)malloc(num_nodes * sizeof(struct Edge));
for (j = 0; j < num_nodes; j++) {
nodes[i][j].to = -1;
nodes[i][j].cost = -1;
}
}

nodes[0][0].to = 1; nodes[0][0].cost = 4;
nodes[0][1].to = 2; nodes[0][1].cost = 2;
nodes[1][0].to = 3; nodes[1][0].cost = 1;
nodes[2][0].to = 1; nodes[2][0].cost = 1;
nodes[2][1].to = 3; nodes[2][1].cost = 5;

int *dist = (int *)malloc(num_nodes * sizeof(int));
dijkstra(nodes, num_nodes, 0, dist);

for (i = 0; i < num_nodes; i++) {
printf("%d ", dist[i]);
}
printf("\n");

for (i = 0; i < num_nodes; i++) {
free(nodes[i]);
}
free(nodes);
free(dist);

return 0;
}
78 changes: 78 additions & 0 deletions dijkstra.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
type edge struct {
to int
cost int
}

type node struct {
id int
dist int
edges []edge
}

func dijkstra(nodes []node, start int) []int {
const inf = 1<<31 - 1
dist := make([]int, len(nodes))
for i := range dist {
dist[i] = inf
}
dist[start] = 0
pq := priorityQueue{{start, 0}}
for len(pq) > 0 {
curr := pq.pop()
if dist[curr.id] < curr.dist {
continue
}
for _, e := range nodes[curr.id].edges {
if newDist := dist[curr.id] + e.cost; newDist < dist[e.to] {
dist[e.to] = newDist
pq.push(node{e.to, newDist})
}
}
}
return dist
}

type priorityQueue []node

func (pq *priorityQueue) push(n node) {
heap.Push(pq, n)
}

func (pq *priorityQueue) pop() node {
return heap.Pop(pq).(node)
}

func (pq priorityQueue) Len() int {
return len(pq)
}

func (pq priorityQueue) Less(i, j int) bool {
return pq[i].dist < pq[j].dist
}

func (pq priorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
}

func (pq *priorityQueue) Push(x interface{}) {
*pq = append(*pq, x.(node))
}

func (pq *priorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
*pq = old[0 : n-1]
return item
}

func main() {
nodes := []node{
{0, 0, []edge{{1, 4}, {2, 2}}},
{1, math.MaxInt32, []edge{{3, 1}}},
{2, math.MaxInt32, []edge{{1, 1}, {3, 5}}},
{3, math.MaxInt32, []edge{}},
}
dist := dijkstra(nodes, 0)
fmt.Println(dist)
}
59 changes: 59 additions & 0 deletions dijkstra.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::cmp::Ordering;
use std::collections::BinaryHeap;

#[derive(Clone, Copy, Eq, PartialEq)]
struct Node {
id: usize,
dist: i32,
}

impl Ord for Node {
fn cmp(&self, other: &Node) -> Ordering {
other.dist.cmp(&self.dist)
}
}

impl PartialOrd for Node {
fn partial_cmp(&self, other: &Node) -> Option<Ordering> {
Some(self.cmp(other))
}
}

struct Edge {
to: usize,
cost: i32,
}

fn dijkstra(nodes: &Vec<Vec<Edge>>, start: usize) -> Vec<i32> {
let mut dist = vec![i32::MAX; nodes.len()];
let mut pq = BinaryHeap::new();

dist[start] = 0;
pq.push(Node { id: start, dist: 0 });

while let Some(Node { id, dist: _ }) = pq.pop() {
for edge in &nodes[id] {
let new_dist = dist[id] + edge.cost;
if new_dist < dist[edge.to] {
dist[edge.to] = new_dist;
pq.push(Node {
id: edge.to,
dist: new_dist,
});
}
}
}

dist
}

fn main() {
let nodes = vec![
vec![Edge { to: 1, cost: 4 }, Edge { to: 2, cost: 2 }],
vec![Edge { to: 3, cost: 1 }],
vec![Edge { to: 1, cost: 1 }, Edge { to: 3, cost: 5 }],
vec![],
];
let dist = dijkstra(&nodes, 0);
println!("{:?}", dist);
}
2 changes: 1 addition & 1 deletion dijkstras.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@ g.addVertex 'H',
E: 1
F: 3

console.log g.shortestPath('A', 'H').concat(['A']).reverse()
console.log g.shortestPath('A', 'H').concat(['A']).reverse()
2 changes: 1 addition & 1 deletion dijkstras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ int main()
}

return 0;
}
}
2 changes: 1 addition & 1 deletion dijkstras.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@ public static void Main(string[] args)
g.shortest_path('A', 'H').ForEach( x => Console.WriteLine(x) );
}
}
}
}
2 changes: 1 addition & 1 deletion dijkstras.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,4 @@ g.addVertex('G', {C: 4, F: 9});
g.addVertex('H', {E: 1, F: 3});

// Log test, with the addition of reversing the path and prepending the first node so it's more readable
console.log(g.shortestPath('A', 'H').concat(['A']).reverse());
console.log(g.shortestPath('A', 'H').concat(['A']).reverse());
2 changes: 1 addition & 1 deletion dijkstras.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ public function __toString()
$graph->add_vertex( 'F', array( 'B' => 2, 'C' => 6, 'D' => 8, 'G' => 9, 'H' => 3 ) );
$graph->add_vertex( 'G', array( 'C' => 4, 'F' => 9 ) );
$graph->add_vertex( 'H', array( 'E' => 1, 'F' => 3 ) );
print_r($graph->shortest_path('A', 'H'));
print_r($graph->shortest_path('A', 'H'));