All technological notes.
Graph
vertices and edges.A graph is an ordered pair G=(V,E) comprising:
V, a set of vertices (also called nodes or points);E, a set of edges (also called links or lines), which are unordered pairs of vertices (that is, an edge is associated with two distinct vertices). Each edge is a tuple (v,w) where w,v∈VComponents of a Graph
Vertex / Vertices
node / nodes.the fundamental units of the graph.
Key
vertexPayload
Edges
lines, links, or arcs.Weight
Path
unweighted path length
weighted path length
Subgraph
Undirected Graph
Directed Graph
digraphcycle graph
Cyclic Graph
acyclic graph
directed acyclic graph or DAG
There are two ways to store a graph:
| Action | Adjacency Matrix | Adjacency List |
|---|---|---|
| Adding Edge | O(1) | O(1) |
| Removing an edge | O(1) | O(N) |
| Initializing | O(N*N) | O(N) |
Adjacency Matrix

In this matrix implementation, each of the rows and columns represent a vertex in the graph.
The value stored in the cell at the intersection of row v and column w indicates if there is an edge from vertex v to vertex w.
When two vertices are connected by an edge, we say that they are adjacent.
Sparse matrix
Full matrix
Advantage of the adjacency matrix
a good implementation for a graph when the number of edges is large.
| Since there is one row and one column for every vertex in the graph, the number of edges required to fill the matrix is ** | V | ^2**. |
Adjacency List
In an adjacency list implementation we keep a master list of all the vertices in the Graph object and then each vertex object in the graph maintains a list of the other vertices that it is connected to.
In our implementation of the Vertex class we will use a dictionary rather than a list where the dictionary keys are the vertices, and the values are the weights.
Advantage of the adjacency list implementation

class Vertex(object):
'''Implement vertex'''
def __init__(self, key):
self.id = key # key of current vertex
self.neighbor = {} # initialize neighbors of current vertex
def __str__(self):
return 'Vertex {0} connects to {1}'.format(self.id, str([x.id for x in self.neighbor]))
def get_id(self):
return self.id
def add_neighbor(self, vertex, weight):
'''add a target vertex with specific weight'''
# Note that the key here is vertex, an object
self.neighbor[vertex] = weight
# set weight for both current and target vertex
vertex.neighbor[self] = weight
def get_neighbors(self):
'''get all neighbors'''
return [k for k in self.neighbor.keys()]
def get_weight(self, target_vertex):
'''get weight from current to target vertex'''
# if target is in the neighbors
if target_vertex in self.neighbor:
return self.neighbor[target_vertex]
else:
return None
class Graph(object):
def __init__(self) -> None:
self.vertice = {}
def add_vertex(self, key):
'''create a new vertex with key'''
new_vertext = Vertex(key) # create a new vertex
self.vertice[key] = new_vertext
return new_vertext
def get_vertex(self, key):
if key in self.vertice.keys():
return self.vertice[key]
else:
None
def add_edge(self, from_key, to_key, cost=0):
'''add edge'''
# if from key does not exist, then create a new vertex
if from_key not in self.vertice:
self.add_vertex(from_key)
# if to key does not exist, then create a new vertex
if to_key not in self.vertice:
self.add_vertex(to_key)
self.vertice[from_key].add_neighbor(self.vertice[to_key], cost)
def get_all_vertice(self):
'''get all vertice'''
return [k for k in self.vertice.keys()]
def __iter__(self):
return iter(self.vertList.values())
def __contains__(self, key):
return key in self.vertice
g = Graph()
for i in range(6):
g.add_vertex(i)
print(g.get_vertex(0)) # Vertex 0 connects to []
g.add_edge(0, 1, 1)
g.add_edge(0, 2, 2)
g.add_edge(0, 3, 3)
g.add_edge(0, 7, 3)
print(g.get_vertex(0)) # Vertex 0 connects to [1, 2, 3, 7]
print(g.get_vertex(1)) # Vertex 1 connects to [0]
print(g.get_vertex(2)) # Vertex 2 connects to [0]
print(g.get_vertex(3)) # Vertex 3 connects to [0]
print(g.get_vertex(0)) # Vertex 0 connects to [1, 2, 3, 7]
g.get_all_vertice() # [0, 1, 2, 3, 4, 5, 7]
3 in g # True
10 in g # False
word ladder.
example
Solution:
breadth first search to find an efficient path from the starting word to the ending word.Steps:
class Vertex:
def __init__(self,key):
self.id = key
self.connectedTo = {}
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])
def getConnections(self):
return self.connectedTo.keys()
def getId(self):
return self.id
def getWeight(self,nbr):
return self.connectedTo[nbr]
class Graph:
def __init__(self):
self.vertList = {}
self.numVertices = 0
def addVertex(self,key):
self.numVertices = self.numVertices + 1
newVertex = Vertex(key)
self.vertList[key] = newVertex
return newVertex
def getVertex(self,n):
if n in self.vertList:
return self.vertList[n]
else:
return None
def __contains__(self,n):
return n in self.vertList
def addEdge(self,f,t,cost=0):
if f not in self.vertList:
nv = self.addVertex(f)
if t not in self.vertList:
nv = self.addVertex(t)
self.vertList[f].addNeighbor(self.vertList[t], cost)
def getVertices(self):
return self.vertList.keys()
def __iter__(self):
return iter(self.vertList.values())
def buildGraph(wordFile):
'''function to build graph'''
d = {}
g = Graph()
# 读取单词文件
wfile = open(wordFile,'r')
# create buckets of words that differ by one letter
for line in wfile:
print(line)
word = line[:-1] # 该处-1是去除换行号\n
print(word)
for i in range(len(word)):
bucket = word[:i] + '_' + word[i+1:] #该处按字母顺序替换为"_"符号作为bucket
if bucket in d:
d[bucket].append(word) # bucket作为字典的键, 目的是如果单词特征相同的,加入到value
else:
d[bucket] = [word] # 如果bucket不存在, 则加入, 注意value是list
# add vertices and edges for words in the same bucket
# 思路:
# 1.遍历所有单词特征
# 2.嵌套遍历相同特征下的list的成员,
# 3.如果不是相同单词时, 向graph对象添加edge
# 效果: 有相同特征的单词之间建立关联
for bucket in d.keys():
for word1 in d[bucket]:
for word2 in d[bucket]:
if word1 != word2:
g.addEdge(word1,word2)
return g
Definition
Algorithm
Use case
Algorithm
Use case