Python custom adjacency table graph class

Graph abstract data type (ADT) terminology:
Vertex: Also known as node, is the basic part of a graph. Has the name identifier "key". Vertices can also have additional information item "playload".

Edge: Also known as arc, is also the basic component of a graph. If an edge connects two vertices, it means that they are connected. Edges can be either one-way or two-way. If the edges of a graph are unidirectional, the graph is called a directed graph/digraph.

Weight: To express the "cost" of moving from one vertex to another, edges can be weighted.

Path: The path in the graph is a sequence of vertices connected by edges in turn. The length of the weightless path is the number of edges. The length of the weighted path is the sum of the weights of all edges.

Cycle: The circle in a digraph is the same path as the first and last vertices. Graphs without cycles are called "acyclic graphs" and directed acyclic graph s or DAGs without cycles.

Two famous methods for realizing graphs are adjacency matrix and adjacency list.

Advantages and disadvantages of adjacency matrix and adjacency table:
In a two-dimensional matrix, each row and column represents the vertex of the graph. If there are edges between vertex v and vertex w, the values are stored in the V rows and W columns of the matrix. The value of each lattice represents the weight from vertex v to vertex W.
Advantages of adjacency matrix: It is simple, however, most of the matrices are empty. In this case, the matrix is called "sparse". Matrix is not an effective way to store sparse data.
A more efficient way to implement sparse graphs is to use adjacency lists. In this implementation method, a master list containing all vertices is included, each vertex in the main list is associated with a list of all vertices connected with its own edge. In the method of implementing vertex classes, dictionaries are used instead of lists, keys in dictionaries correspond to vertices, and values preserve the weights of vertex join edges.
The advantage of adjacency table is that it can efficiently represent a sparse graph. The adjacency table can also easily find all connections between a vertex and other vertices.

Custom Vertex Class

class Vertex(object):
	# Initialization vertex
	def __init__(self, key):
		self.id = key 							#Key to Initialize Vertex
		self.connectedTo = {}					#Initialization Vertex Value

	# Add neighbor vertex, parameter nbr is the key of neighbor vertex, default weight is 0	
	def addNeighbor(self, nbr, weight=0):
		self.connectedTo[nbr] = weight

	def __str__(self):
		return str(self.id) + ' connectedTo: ' + str([x.id for x in self.connectedTo])

	# The key to get all neighbor vertices of the vertex
	def getConnections(self):
		return self.connectedTo.keys()

	# The key to get the vertex
	def getId(self):
		return self.id

	# Get the weight of a neighbor's vertex
	def getWeight(self, nbr):
		return self.connectedTo[nbr]

# Custom Graph Class
class Graph(object):
	# Initialization diagram
	def __init__(self):
		self.vertList = {}						#Initialize adjacency table
		self.numVertices = 0 					#Number of initialization vertices

	# add vertex
	def addVertex(self, key):
		newVertex = Vertex(key)					#Create vertices
		self.vertList[key] = newVertex 			#Add a new vertex to the adjacency table
		self.numVertices = self.numVertices + 1 #Number of vertices + 1 in adjacency list
		return newVertex

	# Get the vertex
	def getVertex(self, n):
		if n in self.vertList:					#If the vertex to be queried is in the adjacency table,
			return self.vertList[n] 			#Return the vertex
		else:
			return None

	# Make it available to in method
	def __contains__(self, n):
		return n in self.vertList

	# Add edges, parameter f is the key of the starting vertex, t is the key of the target vertex, and cost is the weight.
	def addEdge(self, f, t, cost=0):
		if f not in self.vertList:				#If the starting vertex is not in the adjacency list, then
			self.addVertex(f) 					#Add start vertex
		if t not in self.vertList:				#If the target vertex is not in the adjacency list, then
			self.addVertex(t)					#Add target vertices
		self.vertList[f].addNeighbor(self.vertList[t], cost)#Target Points and Weights of Starting Points in Adjacency Table

	# Get the keys of all vertices in the adjacent table
	def getVertices(self):
		return self.vertList.keys()

	# Iterative display of neighbor nodes for each vertex of adjacent table
	def __iter__(self):
		return iter(self.vertList.values())


g = Graph() 									#Instance Graph Class
for i in range(6): 
	g.addVertex(i) 								#Adding nodes to adjacent tables
print(g.vertList)								#Print adjacency table
g.addEdge(0, 1, 5) 								#Adding edges and weights to adjacency tables
g.addEdge(0, 5, 2) 
g.addEdge(1, 2, 4) 
g.addEdge(2, 3, 9) 
g.addEdge(3, 4, 7) 
g.addEdge(3, 5, 3) 
g.addEdge(4, 0, 1) 
g.addEdge(5, 4, 8) 
g.addEdge(5, 2, 1) 
for v in g: 									#Cycle each vertex
	for w in v.getConnections(): 				#Loop all neighbor nodes of each vertex
		print("(%s, %s)" % (v.getId(), w.getId())) #Print the keys of vertices and their neighbors

The result is:

{0: <__main__.Vertex object at 0x00000000021BF828>, 1: <__main__.Vertex object at 0x00000000021BF860>, 2: <__main__.Vertex object at 0x00000000021BF898>, 3: <__main__.Vertex object at 0x00000000021BF8D0>, 4: <__main__.Vertex object at 0x00000000021BF908>, 5: <__main__.Vertex object at 0x00000000021BF940>}
(0, 1)
(0, 5)
(1, 2)
(2, 3)
(3, 4)
(3, 5)
(4, 0)
(5, 4)
(5, 2)

Added by bgomillion on Wed, 15 May 2019 10:47:09 +0300