What does this line do?
node.next = self.graph[src]
EX: [1:2] here I know how to make 2 as a node, then make index 1 equal it, but what if i have [1:3] too, how to add 3 to 2?
Here's the full code of Adjacency List implementation
class AdjNode:
def __init__(self, data):
self.vertex = data
self.next = None
class Graph:
def __init__(self, vertices):
self.vertices = vertices
self.graph = [None] * self.vertices
def add_edge(self, src, dest):
node = AdjNode(dest)
#==================================================
node.next = self.graph[src]
#==================================================
self.graph[src] = node
def print_graph(self):
for i in range(self.vertices):
print("Adjacency list of vertex {}\n {}".format(i,i), end="")
temp = self.graph[i]
while temp:
print(" -> {}".format(temp.vertex), end="")
temp = temp.next
print(" \n")
V = 5
graph = Graph(V)
graph.add_edge(0, 1)
graph.add_edge(0, 4)
graph.add_edge(1, 2)
graph.add_edge(1, 3)
graph.add_edge(1, 4)
graph.add_edge(2, 3)
graph.add_edge(3, 4)
graph.print_graph()
Output
Adjacency list of vertex 0
0 -> 4 -> 1
Adjacency list of vertex 1
1 -> 4 -> 3 -> 2
Adjacency list of vertex 2
2 -> 3
Adjacency list of vertex 3
3 -> 4
Adjacency list of vertex 4
4
CodePudding user response:
EX: [1:2] here I know how to make 2 as a node, then make index 1 equal it, but what if i have [1:3] too, how to add 3 to 2?
It may help to visualise the process. So let's say there are four nodes, numbered 0, 1, 2 and 3, then we have self.graph
initialised as follows (boxes are accessed by index):
self.graph
↓
┌─────────┬─────────┬─────────┬─────────┐
│ 0: None │ 1: None │ 2: None │ 3: None │
└─────────┴─────────┴─────────┴─────────┘
Let's say graph.add_edge(1, 2)
would be the first action on that graph, so then src
is 1 and dst
is 2. The first statement node = AdjNode(dest)
will bring this state:
self.graph
↓
┌─────────┬─────────┬─────────┬─────────┐
│ 0: None │ 1: None │ 2: None │ 3: None │
└─────────┴─────────┴─────────┴─────────┘
┌────────────┐
node → │ vertex: 2 │
│ next: None │
└────────────┘
The next statement node.next = self.graph[src]
doesn't do much now, as it just assigns None
to node.next
, which is already there. Finally, graph[src] = node
does make an important link:
self.graph
↓
┌─────────┬─────────┬─────────┬─────────┐
│ 0: None │ 1: ─┐ │ 2: None │ 3: None │
└─────────┴─────│───┴─────────┴─────────┘
│
│
│
▼
┌────────────┐
node → │ vertex: 2 │
│ next: None │
└────────────┘
Then the function returns, and node
is no longer a name that is in scope.
Now, let's look at what graph.add_edge(1, 3)
does. So src
is 1 again, but dst
is 3. The usual node is created with node = AdjNode(dest)
giving this state (with a new node
name for the new node):
self.graph
↓
┌─────────┬─────────┬─────────┬─────────┐
│ 0: None │ 1: ─┐ │ 2: None │ 3: None │
└─────────┴─────│───┴─────────┴─────────┘
node │
↓ │
┌────────────┐ │
│ vertex: 3 │ │
│ next: None │ │
└────────────┘ │
▼
┌────────────┐
│ vertex: 2 │
│ next: None │
└────────────┘
And now the "magic" assignment happens: node.next = self.graph[src]
. This will copy the reference that is at self.graph[src]
into node.next
. In the image that means the arrow is copied so that they point to the same thing:
self.graph
↓
┌─────────┬─────────┬─────────┬─────────┐
│ 0: None │ 1: ─┐ │ 2: None │ 3: None │
└─────────┴─────│───┴─────────┴─────────┘
node │
↓ │
┌────────────┐ │
│ vertex: 3 │ │
│ next: ─┐ │ │
└────────│───┘ │
▼ ▼
┌────────────┐
│ vertex: 2 │
│ next: None │
└────────────┘
And finally, we execute graph[src] = node
:
self.graph
↓
┌─────────┬─────────┬─────────┬─────────┐
│ 0: None │ 1: ─┐ │ 2: None │ 3: None │
└─────────┴─────│───┴─────────┴─────────┘
node │
↓ ▼
┌────────────┐
│ vertex: 3 │
│ next: ─┐ │
└────────│───┘
▼
┌────────────┐
│ vertex: 2 │
│ next: None │
└────────────┘
So, after all this, the later destination node was prefixed to a linked list before the node(s) that were already in the list that started at self.graph[src]
.
I hope this clarifies it.