How to represent graph's node/vertex as alphabetic or name value instead of numeric

Question:

This is the code I wrote for Graph structure, which works in the value passed in numeric

class Graph:
    def __init__(self, nVertices):
        self.nVertices = nVertices
        self.adjList = [[]for i in range(nVertices)]
        
    def addEdge(self, v1, v2):
        self.adjList[v1].append(v2)
        self.adjList[v2].append(v1)
    
    def dfs(self, sv, visited):
        print(sv)
        visited[sv] = True
        for i in self.adjList[sv]:
            if visited[i] is False:
                self.dfs(i, visited)

    def removeEdge(self, v1, v2):
        if self.containsEdge(v1, v2) is False:
            return
        self.adjList[v1].remove(v2)
        self.adjList[v2].remove(v1)
        
    def containsEdge(self, v1, v2):
        return True if v2 in self.adjList[v1] else False

    def __str__(self):
        return str(self.adjList)

Main Program, to make use of Graph Class, using which we can create graph with nodes and edges

g = Graph(6)
g.addEdge(0, 2)
g.addEdge(0, 4)
g.addEdge(1, 2)

g.dfs(0, [False for i in range(g.nVertices)])
print(g)

Now what I want, when I pass the string values

g = Graph(6)
g.addEdge('A', 'B')
g.addEdge('B', 'E')
g.addEdge('E', 'F')

g.dfs(0, [False for i in range(g.nVertices)])
print(g)

it should work, but its not, since my edge function is written like that, and I am not sure how to implement that. Some key value thing will be useful I believe, but not sure how to make it work.

Kindly help me figure that out:)

Asked By: Suraj Singh

||

Answers:

You could define your adjList attribute as a dictionary of lists:

    self.adjList = defaultdict(list)

Also the visited structure needs to change. I would suggest a set instead of a list of booleans, and it should start as an empty set.

The driver code surely needs to change. Passing 0 as first argument to dfs is meaningless as there is no node that is identified by 0 any more.

Finally, nVertices is not really useful now, as you really need to provide the labels of all vertices anyway. I would just drop it.

Unrelated, but containsEdge does not need an if..else operator. Just return the value of the expression that is already a boolean.

Here is the adapted code:

from collections  import defaultdict

class Graph:
    def __init__(self):
        self.adjList = defaultdict(list)  # Not list of lists, but dict of lists
        
    def addEdge(self, v1, v2):
        self.adjList[v1].append(v2)
        self.adjList[v2].append(v1)
    
    def dfs(self, sv, visited):
        print(sv)
        visited.add(sv)  # No list of booleans, but set
        for i in self.adjList[sv]:
            if i not in visited:  # Set membership test
                self.dfs(i, visited)

    def removeEdge(self, v1, v2):
        if self.containsEdge(v1, v2) is False:
            return
        self.adjList[v1].remove(v2)
        self.adjList[v2].remove(v1)
        
    def containsEdge(self, v1, v2):
        return v2 in self.adjList[v1]  # Simplified expression

    def __str__(self):
        return dict.__repr__(self.adjList)  # Use standard dict representation

g = Graph()
g.addEdge('A', 'B')
g.addEdge('B', 'E')
g.addEdge('E', 'F')
g.dfs('A', set())  # Adapt arguments to new data structure
print(g)
Answered By: trincot