Graph Implementation Using Adjacency Lists and Matirx

在这里插入图片描述

Graph Implementation Using Adjacency Lists

for an undirected graph.
© Joe James, 2019.

Vertex Class

The Vertex class has a constructor that sets the name of the vertex (in our example, just a letter), and creates a new empty set to store neighbors.

The add_neighbor method adds the name of a neighboring vertex to the neighbors set. This set automatically eliminates duplicates.

class Vertex:
    def __init__(self, n):
        self.name = n
        self.neighbors = set()
    
    def add_neighbor(self, v):
        self.neighbors.add(v)

Graph Class

The Graph class uses a dictionary to store vertices in the format, vertex_name:vertex_object.

Adding a new vertex to the graph, we first check if the object passed in is a vertex object, then we check if it already exists in the graph. If both checks pass, then we add the vertex to the graph’s vertices dictionary.

When adding an edge, we receive two vertex names, we first check if both vertex names are valid, then we add each to the other’s neighbors set.

To print the graph, we iterate through the vertices, and print each vertex name (the key) followed by its sorted neighbors list.

class Graph:
    vertices = {}
    
    def add_vertex(self, vertex):
        if isinstance(vertex, Vertex) and vertex.name not in self.vertices:
            self.vertices[vertex.name] = vertex
            return True
        else:
            return False
    
    def add_edge(self, u, v):
        if u in self.vertices and v in self.vertices:
            self.vertices[u].add_neighbor(v)
            self.vertices[v].add_neighbor(u)
            return True
        else:
            return False
            
    def print_graph(self):
        for key in sorted(list(self.vertices.keys())):
            print(key, sorted(list(self.vertices[key].neighbors)))

Test Code

Here we create a new Graph object. We create a new vertex named A. We add A to the graph. Then we add new vertex B to the graph. Then we iterate from A to K and add a bunch of vertices to the graph. Since the add_vertex method checks for duplicates, A and B are not added twice.

g = Graph()
a = Vertex('A')
g.add_vertex(a)
g.add_vertex(Vertex('B'))
for i in range(ord('A'), ord('K')):
    g.add_vertex(Vertex(chr(i)))

An edge consists of two vertex names. Here we iterate through a list of edges and add each to the graph.

This print_graph method doesn’t give a very good visualization of the graph, but it does show the neighbors for each vertex.

edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']
for edge in edges:
    g.add_edge(edge[0], edge[1])

g.print_graph()
A ['B', 'E']
B ['A', 'F']
C ['G']
D ['E', 'H']
E ['A', 'D', 'H']
F ['B', 'G', 'I', 'J']
G ['C', 'F', 'J']
H ['D', 'E', 'I']
I ['F', 'H']
J ['F', 'G']

Graph Implementation Using Adjacency Matrix

for undirected graph, with weighted or unweighted edges.
© Joe James, 2019.

Vertex Class

A vertex object only needs to store its name.

class Vertex:
    def __init__(self, n):
        self.name = n

Graph Class

A graph object has three attributes:
vertices - a dictionary with vertex_name:vertex_object.
edges - a 2-dimensional list (ie. a matrix) of edges. for an unweighted graph it will contain 0 for no edge and 1 for edge.
edge_indices - a dictionary with vertex_name:list_index (eg. A:0) to access edges.
add_vertex updates all three of these attributes.
add_edge only needs to update the edges matrix.

class Graph:
    vertices = {}
    edges = []
    edge_indices = {}
    
    def add_vertex(self, vertex):
        if isinstance(vertex, Vertex) and vertex.name not in self.vertices:
            self.vertices[vertex.name] = vertex 
            # for loop appends a column of zeros to the edges matrix
            for row in self.edges:
                row.append(0)
            # append a row of zeros to the bottom of the edges matrix
            self.edges.append([0] * (len(self.edges)+1))
            self.edge_indices[vertex.name] = len(self.edge_indices)
            # Exp: Vertices 'A', 'C' and 'B' are added one after another, then self.edge_indices['C'] = 1
            return True
        else:
            return False
    
    def add_edge(self, u, v, weight=1):
        if u in self.vertices and v in self.vertices:
            self.edges[self.edge_indices[u]][self.edge_indices[v]] = weight
            self.edges[self.edge_indices[v]][self.edge_indices[u]] = weight
            return True
        else:
            return False
            
    def print_graph(self):
        print(self.edge_indices)
        for v, i in sorted(self.edge_indices.items()):
            print(v + ' ', end='')
            for j in range(len(self.edges)):
                print(self.edges[i][j], end=' ')
            print(' ')

Test Code

Here we create a new Graph object. We create a new vertex named A. We add A to the graph. Then we add new vertex B to the graph. Then we iterate from A to K and add a bunch of vertices to the graph. Since the add_vertex method checks for duplicates, A and B are not added twice.
This is exactly the same test code we used for the graph with adjacency lists.

g = Graph()
a = Vertex('A')
g.add_vertex(a)
g.add_vertex(Vertex('B'))
for i in range(ord('A'), ord('K')):
    g.add_vertex(Vertex(chr(i)))

An edge consists of two vertex names. Here we iterate through a list of edges and add each to the graph.

This print_graph method doesn’t give a very good visualization of the graph, but it does show the adjacency matrix so we can see each vertex’s neighbors.

edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']
for edge in edges:
    g.add_edge(edge[0], edge[1])

g.print_graph()
{'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9}
A 0 1 0 0 1 0 0 0 0 0  
B 1 0 0 0 0 1 0 0 0 0  
C 0 0 0 0 0 0 1 0 0 0  
D 0 0 0 0 1 0 0 1 0 0  
E 1 0 0 1 0 0 0 1 0 0  
F 0 1 0 0 0 0 1 0 1 1  
G 0 0 1 0 0 1 0 0 0 1  
H 0 0 0 1 1 0 0 0 1 0  
I 0 0 0 0 0 1 0 1 0 0  
J 0 0 0 0 0 1 1 0 0 0  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值