1.“图”这部分分为无向图 、有向图、无向网(带权图)、有向网(带权图)四个内容。
图的顺序存储:邻接矩阵的存储形式
图的链式存储与顺序存储的组合:邻接表的存储形式
2.图的邻接矩阵存储
(1)无向图:
- 无向图的邻接矩阵是对称的,是一个对称矩阵
- 顶点i的度=第i行(列)中1的个数
- 特别:完全图的邻接矩阵中,对角元素为0,其余为1
(2)有向图:
- 第i行的含义:顶点vi的出度
- 第i列的含义:顶点vi的入度
- 有向图的邻接矩阵可能是不对称的
- 顶点的出度 = 第i行元素之和
- 顶点的入度 = 第i列元素之和
#构建无向图的邻接矩阵
class GraphAX():
def __init__(self,vertex,mat): #vertex为顶点表,mat为边的信息
self.vertex = vertex
self.mat = [mat[i][:] for i in range(len(vertex))]
#求两顶点间是否有边相连
def get_edge(self,vi,vj):
if vi not in self.vertex or vj not in self.vertex:
print("无效顶点")
return
#获取两顶点在顶点表中的索引
i = self.vertex.index(vi)
j = self.vertex.index(vj)
return self.mat[i][j]
def create_matrix():
nodes = ['v0','v1','v2','v3','v4']
mat = [[0,1,0,1,0],
[1,0,1,0,1],
[0,1,0,1,0],
[1,0,1,0,0],
[0,1,1,0,0]]
graph = GraphAX(nodes,mat)
return graph
if __name__=="__main__":
graph = create_matrix()
print(graph.vertex)
print(graph.mat)
print(graph.get_edge('v1','v2'))
输出:
(3)邻接矩阵的优缺点
特点:
- 统计顶点的度
- 顶点不变,在图中增加/删除边:将二维数组对应分量赋值1或0
- 判断任意两个顶点之间是否相连
- 统计图中有多少条边
缺点:
- 不便于删除结点
- 浪费空间,空间复杂度为,是对于稠密图,不对于稀疏图
- 浪费时间,时间复杂度为
3.图的邻接链表存储:
(1)无向图
#边结点
class Anode():
def __init__(self,index,weight=0):
self.index = index
self.weight = weight
self.next = None
#顶点
class Vnode():
def __init__(self,vdata):
self.vdata = vdata
self.first = None
class Graph():
def __init__(self):
#存放顶点的是一个列表
self.vnodelist = []
#添加顶点
def add_vnode(self,vnodedata):
vnode = Vnode(vnodedata)
self.vnodelist.append(vnode)
#添加边
def add_edge(self,edgedata1,edgedata2,weight=0):
#寻找顶点表中是否有edgedata1的结点
i = 0
#注意:在while循环结束时,i等于len(self.vnodelist),但是要用for循环的话就到len(self.vnodelist)-1就结束了
while i < len(self.vnodelist):
if edgedata1 == self.vnodelist[i].vdata:
n1 = self.vnodelist[i]
break
i += 1
else:
if i == len(self.vnodelist):
self.add_vnode(edgedata1)
n1 = self.vnodelist[i]
#寻找顶点表中是否有edgedata2的结点
i = 0
while i < len(self.vnodelist):
if edgedata2 == self.vnodelist[i].vdata:
n2 = self.vnodelist[i]
break
i += 1
else:
if i == len(self.vnodelist):
self.add_vnode(edgedata2)
n2 = self.vnodelist[i]
#连接顶点与边结点,建立单链表
j = self.vnodelist.index(n2)
anode = Anode(j,weight)
anode.next = n1.first
n1.first = anode
graph = Graph()
while True:
s = input("请输入图的顶点值,当输入!结束")
if s =="!":
break
else:
graph.add_vnode(s)
while True:
s1,s2 = input("请输入边的两个结点,用逗号隔开,当输入!结束").split(',')
if s1 == "!":
break
else:
graph.add_edge(s1,s2)
#打印顶点表中的元素
for i in range(len(graph.vnodelist)):
print(graph.vnodelist[i].vdata)
输出:
为了测试方便,将输入改成直接构建图。
if __name__ =="__main__":
graph = Graph()
graph.add_vnode("v0")
graph.add_vnode("v1")
graph.add_vnode("v2")
graph.add_vnode("v3")
graph.add_edge("v0","v1")
graph.add_edge("v1","v2")
graph.add_edge("v2","v3")
graph.add_edge("v3","v4")
#打印顶点表中的元素
for i in range(len(graph.vnodelist)):
print(graph.vnodelist[i].vdata,end=',')
输出: