|
1 | | - |
2 | 1 | class Graph: |
3 | 2 | def __init__(self): |
4 | 3 | self.vertices: list = [] |
5 | 4 | self.adjacencyList: dict = {} |
6 | 5 | self.colors: dict = {} |
| 6 | + self.previous: dict = {} |
| 7 | + self.distance: dict = {} |
| 8 | + self.time: int = 0 |
| 9 | + self.entry: dict = {} |
| 10 | + self.exit: dict = {} |
| 11 | + self.no_incoming_edges: dict = {} # to avoid looking through whole list |
7 | 12 | self.explored: list = [] |
8 | 13 |
|
9 | 14 | def addVertex(self, label: str): |
10 | 15 | self.vertices.append(label) |
11 | 16 | self.adjacencyList[label]: list = [] |
12 | 17 | self.colors[label] = "white" |
| 18 | + self.distance[label] = 0 |
| 19 | + self.previous[label] = None |
| 20 | + self.no_incoming_edges[label] = label |
13 | 21 |
|
14 | 22 | def addEdge(self, label1: str, label2: str): |
15 | 23 | self.adjacencyList[label1].append(label2) |
| 24 | + if label2 in self.no_incoming_edges: |
| 25 | + del self.no_incoming_edges[label2] # remove vertex, it has incoming edge |
16 | 26 |
|
17 | 27 | def topsort(self): |
18 | | - for vertex in self.vertices: |
19 | | - if self.colors[vertex] == "white": |
20 | | - self.dfs(vertex) |
| 28 | + # perform depth first search on vertices with no incoming edges |
| 29 | + for label in self.no_incoming_edges: |
| 30 | + self.dfs(label) |
21 | 31 | self.explored.reverse() |
22 | 32 | print(self.explored) |
23 | | - |
24 | | - def dfs(self, label: str): |
25 | | - self.colors[label] = "gray" |
26 | | - for neighbour in self.adjacencyList[label]: |
| 33 | + |
| 34 | + def dfs(self, start: str): |
| 35 | + self.time += 1 |
| 36 | + self.entry[start] = self.time |
| 37 | + self.colors[start] = "gray" |
| 38 | + for neighbour in self.adjacencyList[start]: |
27 | 39 | if self.colors[neighbour] == "white": |
28 | | - self.colors[neighbour] = "gray" |
| 40 | + self.previous[neighbour] = start |
| 41 | + self.distance[neighbour] = self.distance[neighbour] + 1 |
29 | 42 | self.dfs(neighbour) |
30 | | - self.explored.append(label) |
31 | | - self.colors[label] = "black" |
32 | | - |
33 | | - |
34 | | - |
35 | | - |
36 | | - |
37 | | - |
38 | | - |
| 43 | + self.time += 1 |
| 44 | + self.exit[start] = self.time |
| 45 | + self.colors[start] = "black" |
| 46 | + self.explored.append(start) |
| 47 | + |
| 48 | + def showPath(self, label: str)->str: |
| 49 | + if self.previous[label] is None: |
| 50 | + return label |
| 51 | + else: |
| 52 | + return self.showPath(self.previous[label]) + " -> " + label |
39 | 53 |
|
0 commit comments