Skip to content

Commit dbc25f2

Browse files
committed
graphs
1 parent 510cc20 commit dbc25f2

File tree

11 files changed

+300
-0
lines changed

11 files changed

+300
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
from vertex import Vertex
2+
from priorityqueue import PriorityQueue
3+
4+
5+
class Graph:
6+
def __init__(self):
7+
self._vertices: dict = {}
8+
self._prev: dict = {}
9+
self._adjacency_map: dict = {}
10+
11+
def add_vertex(self, label: str = None, weight: int = float("inf")):
12+
self._vertices[label] = Vertex(label)
13+
self._prev[label] = None
14+
self._adjacency_map[label]: dict = {}
15+
16+
def add_edge(self, label1: str = None, label2: str = None, weight: int = float("inf")):
17+
self._adjacency_map[label1][label2] = Vertex(label2, weight)
18+
19+
def dijkstra(self, label: str):
20+
self._vertices[label].set_weight(0)
21+
pq: PriorityQueue = PriorityQueue()
22+
for vertex_label in self._vertices:
23+
pq.insert(self._vertices[vertex_label])
24+
while not pq.is_empty():
25+
vertex: Vertex = pq.delete_min()
26+
for neighbour_label in self._adjacency_map[vertex.get_label()]:
27+
neighbour_from_adjacency_map: Vertex = self._adjacency_map[vertex.get_label()][neighbour_label]
28+
neighbour_from_vertices: Vertex = self._vertices[neighbour_label]
29+
if neighbour_from_vertices.get_weight() > \
30+
vertex.get_weight() + neighbour_from_adjacency_map.get_weight():
31+
neighbour_from_vertices.set_weight(vertex.get_weight() + neighbour_from_adjacency_map.get_weight())
32+
self._prev[neighbour_from_vertices.get_label()] = vertex.get_label()
33+
pq.decrease_key(neighbour_from_vertices.get_key())
34+
35+
def return_path(self, end_label: str = None) -> str:
36+
if self._prev[end_label] is None:
37+
return end_label
38+
else:
39+
return self.return_path(self._prev[end_label]) + " -> " + end_label
40+
41+
42+
43+
44+
45+
46+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from graph import Graph
2+
3+
4+
graph: Graph = Graph()
5+
6+
graph.add_vertex("START")
7+
graph.add_vertex("A")
8+
graph.add_vertex("C")
9+
graph.add_vertex("B")
10+
graph.add_vertex("D")
11+
graph.add_vertex("END")
12+
13+
graph.add_edge("START", "A", 0)
14+
graph.add_edge("START", "C", 2)
15+
graph.add_edge("A", "B", 18)
16+
graph.add_edge("A", "D", 15)
17+
graph.add_edge("C", "B", 3)
18+
graph.add_edge("C", "D", 10)
19+
graph.add_edge("B", "END", 150)
20+
graph.add_edge("D", "END", 15)
21+
graph.dijkstra("START")
22+
23+
print(graph.return_path("END"))
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from vertex import Vertex
2+
3+
4+
class PriorityQueue:
5+
def __init__(self):
6+
self._queue: list = [None]
7+
self._pointer: int = 0
8+
9+
def is_empty(self) -> bool:
10+
return self._pointer == 0
11+
12+
def insert(self, vertex: Vertex):
13+
self._queue.append(vertex)
14+
self._pointer += 1
15+
vertex.set_key(self._pointer)
16+
self._perc_up(self._pointer)
17+
18+
def _perc_up(self, index: int):
19+
while index // 2 > 0:
20+
if self._queue[index].get_weight() < self._queue[index // 2].get_weight():
21+
self._queue[index], self._queue[index // 2] = self._queue[index // 2], self._queue[index]
22+
self._queue[index].set_key(index)
23+
self._queue[index // 2].set_key(index // 2)
24+
index = index // 2
25+
26+
def decrease_key(self, key: int):
27+
self._perc_up(key)
28+
29+
def delete_min(self) -> Vertex:
30+
if self.is_empty():
31+
raise Exception("Priority Queue is empty")
32+
vertex_to_delete: Vertex = self._queue[1]
33+
self._queue[1] = self._queue[self._pointer]
34+
self._queue[1].set_key(1)
35+
self._pointer -= 1
36+
self._queue.pop()
37+
self._perc_down(1)
38+
return vertex_to_delete
39+
40+
def _perc_down(self, index: int):
41+
while index * 2 <= self._pointer:
42+
swap_index: int = self._find_swap_index(index)
43+
if self._queue[index].get_weight() > self._queue[swap_index].get_weight():
44+
self._queue[index], self._queue[swap_index] = self._queue[swap_index], self._queue[index]
45+
self._queue[index].set_key(index)
46+
self._queue[swap_index].set_key(swap_index)
47+
index = swap_index
48+
49+
def _find_swap_index(self, index) -> int:
50+
if index * 2 + 1 > self._pointer:
51+
return index * 2
52+
else:
53+
if self._queue[index * 2].get_weight() <= self._queue[index * 2 + 1].get_weight():
54+
return index * 2
55+
else:
56+
return index * 2 + 1
57+
58+
59+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Vertex:
2+
def __init__(self, label: str = None, weight: int = float("inf"), key: int = None):
3+
self._label: str = label
4+
self._weight: int = weight
5+
self._key: int = key
6+
7+
def get_label(self) -> str:
8+
return self._label
9+
10+
def set_key(self, key: int):
11+
self._key = key
12+
13+
def get_key(self) -> int:
14+
return self._key
15+
16+
def set_weight(self, weight: int = float("inf")):
17+
self._weight = weight
18+
19+
def get_weight(self) -> int:
20+
return self._weight

graphs/prims-algorithm/graph.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from vertex import Vertex
2+
from priorityqueue import PriorityQueue
3+
4+
5+
class Graph:
6+
def __init__(self):
7+
self._vertices: dict = {}
8+
self._prev: dict = {}
9+
self._adjacency_map: dict = {}
10+
11+
def add_vertex(self, label: str = None, weight: int = float("inf")):
12+
self._vertices[label] = Vertex(label)
13+
self._prev[label] = None
14+
self._adjacency_map[label]: dict = {}
15+
16+
def add_edge(self, label1: str = None, label2: str = None, weight: int = float("inf")):
17+
self._adjacency_map[label1][label2] = Vertex(label2, weight)
18+
self._adjacency_map[label2][label1] = Vertex(label1, weight)
19+
20+
def prims(self, label: str):
21+
result: str = ""
22+
self._vertices[label].set_weight(0)
23+
pq: PriorityQueue = PriorityQueue()
24+
for vertex_label in self._vertices:
25+
pq.insert(self._vertices[vertex_label])
26+
while not pq.is_empty():
27+
vertex: Vertex = pq.delete_min()
28+
if self._prev[vertex.get_label()] is not None:
29+
result += self._prev[vertex.get_label()] + " -> " + vertex.get_label() + ", "
30+
for neighbour_label in self._adjacency_map[vertex.get_label()]:
31+
neighbour_from_adjacency_map: Vertex = self._adjacency_map[vertex.get_label()][neighbour_label]
32+
neighbour_from_vertices: Vertex = self._vertices[neighbour_label]
33+
if neighbour_from_vertices.get_weight() > neighbour_from_adjacency_map.get_weight():
34+
neighbour_from_vertices.set_weight(neighbour_from_adjacency_map.get_weight())
35+
self._prev[neighbour_from_vertices.get_label()] = vertex.get_label()
36+
pq.decrease_key(neighbour_from_vertices.get_key())
37+
print(result)
38+
39+
def return_path(self, end_label: str = None) -> str:
40+
if self._prev[end_label] is None:
41+
return end_label
42+
else:
43+
return self.return_path(self._prev[end_label]) + " -> " + end_label
44+
45+
46+
47+
48+
49+
50+

graphs/prims-algorithm/main.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from graph import Graph
2+
3+
graph: Graph = Graph()
4+
5+
g = Graph()
6+
g.add_vertex("A")
7+
g.add_vertex("B")
8+
g.add_vertex("C")
9+
g.add_vertex("D")
10+
g.add_vertex("E")
11+
g.add_vertex("F")
12+
13+
14+
g.add_edge("A", "B", 4)
15+
g.add_edge("A", "F", 2)
16+
g.add_edge("B", "C", 6)
17+
g.add_edge("F", "B", 3)
18+
g.add_edge("F", "C", 1)
19+
g.add_edge("F", "E", 4)
20+
g.add_edge("C", "D", 3)
21+
g.add_edge("D", "E", 2)
22+
23+
g.prims("A")
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from vertex import Vertex
2+
3+
4+
class PriorityQueue:
5+
def __init__(self):
6+
self._queue: list = [None]
7+
self._pointer: int = 0
8+
9+
def is_empty(self) -> bool:
10+
return self._pointer == 0
11+
12+
def insert(self, vertex: Vertex):
13+
self._queue.append(vertex)
14+
self._pointer += 1
15+
vertex.set_key(self._pointer)
16+
self._perc_up(self._pointer)
17+
18+
def _perc_up(self, index: int):
19+
while index // 2 > 0:
20+
if self._queue[index].get_weight() < self._queue[index // 2].get_weight():
21+
self._queue[index], self._queue[index // 2] = self._queue[index // 2], self._queue[index]
22+
self._queue[index].set_key(index)
23+
self._queue[index // 2].set_key(index // 2)
24+
index = index // 2
25+
26+
def decrease_key(self, key: int):
27+
self._perc_up(key)
28+
29+
def delete_min(self) -> Vertex:
30+
if self.is_empty():
31+
raise Exception("Priority Queue is empty")
32+
vertex_to_delete: Vertex = self._queue[1]
33+
self._queue[1] = self._queue[self._pointer]
34+
self._queue[1].set_key(1)
35+
self._pointer -= 1
36+
self._queue.pop()
37+
self._perc_down(1)
38+
return vertex_to_delete
39+
40+
def _perc_down(self, index: int):
41+
while index * 2 <= self._pointer:
42+
swap_index: int = self._find_swap_index(index)
43+
if self._queue[index].get_weight() > self._queue[swap_index].get_weight():
44+
self._queue[index], self._queue[swap_index] = self._queue[swap_index], self._queue[index]
45+
self._queue[index].set_key(index)
46+
self._queue[swap_index].set_key(swap_index)
47+
index = swap_index
48+
49+
def _find_swap_index(self, index) -> int:
50+
if index * 2 + 1 > self._pointer:
51+
return index * 2
52+
else:
53+
if self._queue[index * 2].get_weight() <= self._queue[index * 2 + 1].get_weight():
54+
return index * 2
55+
else:
56+
return index * 2 + 1
57+
58+
59+

0 commit comments

Comments
 (0)