python实现抽象数据类型=>图(邻接矩阵和邻接表)

一、图的定义

        图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E)。其中G表示图,V表示顶点的集合,E表示边的集合。

        线性表中把数据元素叫做元素,树中将数据元素叫结点,图中数据元素叫顶点。

二、有向图和无向图

        图可以分为有向图和无向图。有向图中的边具有方向,从一个顶点指向另一个顶点,表示一个单向关系。无向图中的边没有方向,连接两个顶点,表示双向关系。

1、无向边和无向图

        如果两个顶点之间的边无方向,则称这条边为无向边,如果图中任意两个顶点之间的边都是无向边,则这个图被称为无向图。

2、有向边和有向图

        如果两个顶点之间的边有方向,则称这条边为无向边,也称为弧(有向边的起点叫弧头,终点叫弧尾),如果图中任意两个顶点之间的边都是有向边,则这个图被称为有向图。

三、稀疏图和稠密图

        根据图中边的数量,图可以分为稀疏图和稠密图。稀疏图中边的数量相对较少,顶点之间的连接比较稀疏。稠密图中边的数量较多,顶点之间的连接较为紧密。

四、完全图

        完全图是指每个顶点都与其他顶点直接相连的图。对于有向图,完全图要求每个顶点都有有向边指向其他顶点,并且每个顶点也接受其他顶点的有向边。完全图分为有向图和无向图。并且完全图一定是稠密图。

五、简单图

        是指图中没有自循环(边的起始顶点和结束顶点相同,比如:顶点1到顶点1有一条边) 和多重边(两个顶点之间存在多条边,比如:顶点1到顶点2有多条边)的图。

六、度

        度是图中顶点的一个重要概念,它表示某个顶点与其他顶点直接相连的边的数量。对于有向图,度分为入度和出度,分别表示指向该顶点的边数和从该顶点指出的边数。

七、权

        是指图中边的附加信息,可以表示边的权重、距离、成本等

八、路径

        路径是图中一系列连续的边,连接了两个顶点。路径可以是有向的和无向的。相关算法就是求两个顶点之间的最短路径。比如Dijkstra算法、Bellman-Ford算法、Floyd算法、Dijkstra+Heap算法、SPFA算法都是求最短路径的算法。

九、连通图和连通分量

        连通图是指图中任意两个顶点之间都存在一条路径。如果图可以划分为多个子图,使得子图内部的顶点连通,而子图之间没有连接,那么这些子图就称为连通分量。

        在有向图中,如果对于任意两个顶点a和b,从a到b和从b到a都存在路径,则称它为强连通图,有向图中的极大强连通子图被称为这个有向图的强连通分量。

十、生成树

        生成数是连通图的一个子图,它是一棵树(没有循环的连通图),并且包含了图中的所有顶点。生成树可以用于图的遍历、最小生成树等问题的解决。常见最小生成树算法有Kruscal和Prim,其中Kruscal用到了并查集。

邻接矩阵

一、临接矩阵的概念

        由于图是由顶点和边(或弧)两部分组成的。顶点可以用一个一维的顺序表来存储,但是边(或弧)由于是顶点与顶点之间的关系,一维搞不定,所以可以考虑用一个二维的顺序表来存储,而二维的顺序表就是一个矩阵。

        对于一个有n个顶点的图G,临接矩阵是一个n*n的方阵(方针就是行列数想等的矩阵)。对于临接矩阵而言,不需要去考虑有向的还是无向的,统一都可以理解成有向的,因为有向图可以兼容无向图,对于无向图而言,只不过这个矩阵是按照主对角线对称的,因为A到B有边,则必然B到A有边。

        对带权图和无权图,临接矩阵的表示略有差别,接下来分别讨论。

未完。。。

实现图共两种方法:

  1. 邻接矩阵
  2. 邻接表

以下代码用邻接矩阵实现

inf = -1

class Graph:
	def __init__(self, n):
		self.n = n  # n个顶点
		self.edges = []  # 邻接矩阵
		for i in range(n):
			L = []
			for j in range(n):
				L.append(inf)
			self.edges.append(L)
			
	def addEdge(self, u, v, w):
		"""
		向邻接矩阵中添加权重
		u: 第u行
		v: 第v列
		w: 权重
		"""
		self.edges[u][v] = w
		
	def printGraph(self):
		"""
		打印邻接矩阵
		"""
		for i in range(self.n):
			for j in range(self.n):
				print(self.edges[i][j], end=" ")
			print('')
			
def test():
	g = Graph(5)
	g.addEdge(0, 1, 1)
	g.addEdge(0, 2, 3)
	g.addEdge(1, 2, 2)
	g.addEdge(2, 3, 7)
	g.addEdge(3, 4, 9)
	g.addEdge(4, 0, 4)
	g.addEdge(4, 2, 5)
	g.printGraph()
	
test()

以下代码用邻接表实现图

class EdgeNode:
	"""
	有向边节点
	"""
	def __init__(self, v, w):
		self.vertex = v   # 弧尾
		self.weight = w   # 权重
		
class VertexNode:
	"""
	有向边节点
	"""
	def __init__(self, v):
		self.vertex = v   # 弧头
		self.edges = []   # 所有弧尾组成的列表
		
class Graph:
	"""
	有向图类
	"""
	def __init__(self, n):
		self.n = n   #有n个顶点
		self.nodes = [VertexNode(i) for i in range(n)]  # 初始化n个弧头节点
		
	def addEdge(self, u, v, w):  #u: 弧头  v: 弧尾   w: 权重
		"""
		将指定的弧尾节点和权重添加到指定的弧头
		"""
		self.nodes[u].edges.append(EdgeNode(v, w))
		
	def printGraph(self):
		"""
		输出图节点
		"""
		for i in range(self.n):
			print("Vertex: ", i, end=":")
			for e in self.nodes[i].edges:
				print(e.vertex, '(', e.weight, ')', end=" ")
			print("")
			
def test():
	g = Graph(5)
	g.addEdge(0, 1, 4)
	g.addEdge(0, 2, 2)
	g.addEdge(1, 2, 3)
	g.addEdge(2, 3, 4)
	g.addEdge(3, 4, 2)
	g.printGraph()
	
test()
		

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值