文章目录
前言
随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了python数据结构图的基础内容。
一、图的基本概念
二、图的存储结构
1.邻接矩阵(MatGraph)
代码如下(示例):
import copy
INF=0x3f3f3f #表示无穷大
class MatGraph:
def __init__(self,n=0,e=0):
self.edges=[] #邻接矩阵
self.vexs=[]
self.n=n #顶点数
self.e=e #边数
def CreateMatGraph(self,a,n,e):
self.n=n
self.e=e
self.edges=copy.deepcopy(a)
def DisMatGraph(self):
for i in range(self.n):
for j in range(self.n):
if self.edges[i][j]==INF:
print("%4s"%("∞"),end='')
else:
print("%4s"%(self.edges[i][j]),end='')
print()
def Degree1(g,v): #在无向图中求顶点V的度
d=0
for i in range(g.n):
if g.edges[v][i]!=INF:
d+=g.edges[v][i]
return d
def Degree2(g,v): #在有向图中求顶点v的度
d=[0,0]
for i in range(g.n):
if g.edges[v][i]!=INF:
d[0]+=g.edges[v][i]
for j in range(g.n):
if g.edges[j][v]!=INF:
d[1]+=g.edges[j][v]
return d[0]+d[1]
m=MatGraph()
a=[
[1,1,1],
[1,0,1],
[0,0,1]
]
m.CreateMatGraph(a,3,3)
m.DisMatGraph()
print(Degree1(m,0))
print(Degree2(m,0))
2.邻接表(AdjGraph)
邻接表每一行表示一个顶点,这一行,表示存放该顶点的所有邻接点以及他们之间的权值。适用于稀疏图和稠密图。
代码如下(示例):
INF=0x3f3f3f
class ArcNode: #边节点类
def __init__(self,adjv,w):
self.adjvex=adjv #一个边结点包括两个东西,邻接点以及权值
self.weight=w
class AdjGraph:
def __init__(self,n,e):
self.adjlist=[] #邻接表
self.vexs=[] #存放顶点信息暂时未用
self.n=n #顶点数
self.e=e #边数
def CreateAdjGraph(self,a,n,e): #创建邻接表
self.n=n
self.e=e
for i in range(n):
adi=[]
for j in range(n):
if a[i][j]!=0 and a[i][j]!=INF:
p=ArcNode(j,a[i][j])
adi.append(p)
self.adjlist.append(adi)
def DisAdjGraph(self):
for i in range(self.n):
print(" [%d]"%(i),end='')
for p in self.adjlist[i]:
print("->(%d,%d)"%(p.adjvex,p.weight),end='')
print("-^")
def Degree1(g,v): #求无向图中顶点v的度
return len(g.adjlist[v])
def Degree2(g,v): #有向图中求顶点v的度
d=[0,0]
d[0] += len(g.adjlist[v]) # 出度
for i in range(g.n):
for p in g.adjlist[i]: #遍历邻接表中的每一个邻接点,如果某一个顶点的邻接点等于v,那么为v的入度之一,循环相加得到v的入度
if p.adjvex==v:
d[1]+=p.weight #书上说是+=1,应该是不考虑有权值
break
return d[0]+d[1]
m=AdjGraph(3,3)
a=[
[1,1,1],
[1,0,1],
[0,1,1]
]
m.CreateAdjGraph(a,3,3)
m.DisAdjGraph()
print(Degree1(m,1))
print(Degree2(m,1))
三、图的遍历
1.深度优先(DFS)
1-1采用邻接表的存储方式
MAXV=100 #全局变量表示最多的顶点数
visited=[0]*MAXV
#以邻接表的方式进行存储
def DFS1(G,v):
print(v,end='')
visited[v]=1
for j in range(len(G.adjlist[v])):
w=G.adjlist[v][j].adjvex
if visited[w]==0:
DFS1(G,w)
#方式二
def DFS2(G,v):
print(v,end='')
visited[v]=1
for p in G.adjlist[v]:
w=p.adjvex
if visited[w]==0:
DFS2(G,w)
1-2采用邻接矩阵的存储
#当用邻接矩阵的方式进行存储时
MAXV=100
visited=[0]*MAXV
def DFS_Mat(G,v):
print(v,end='')
visited[v]=1
for w in range(G.n):
if G.edges[v][w]!=0 and G.edges[v][w]!=INF:
if visited[w]==0:
DFS_Mat(G,w)
2.广度优先 (BFS)
2-1存储结构为邻接表
from collections import deque
MAXV=100
visited=[0]*MAXV
def BFS(G,v):
print(v,end=" ")
qu=deque()
visited[v]=1 #该邻接点被访问,所以标记为1
qu.append(v) #进行入队
while len(qu)>0: #当队列不为空执行
v=qu.popleft() #进行出队,一遍后面用来将这个顶点找邻接点
for j in range(len(G.adjlist[v])): #遍历顶点v的所有邻接点
w=G.adjlist[v][j].adjvex
if visited[w]==0:
print(w,end=" ")
visited[w]=1
qu.append(w)
2-2存储结构为邻接矩阵
#邻接矩阵为存储结构时
def BFS_Mat(G,v):
qu=deque()
print(v,end=" ") #进行遍历
visited[v]=1 #遍历完了标记为1
qu.append(v)
while len(qu)>0:
v=qu.popleft()
for w in range(G.n): #遍历v的所有邻接点
if G.edges[v][w]!=0 and G.edges[v][w]!=INF:
if visited[w]==0:
print(w,end=" ")
visited[w]=1
qu.append(w)
四、非连通图的遍历
4-1 非连通图的DFS
#非连通图的DFS,邻接表存储的图
def DFSA(G):
for i in range(G.n): #遍历图中的每一个顶点
if visited[i]==0: #查看每一个顶点是否访问
DFS1(G,i) #没有访问,则进行深度优先遍历,这样可以保证非连通图也可以对每一个节点进行访问
4-2 非连通图的BFS
#非连通图的BFS
def BFSA(G):
for i in range(G.n):
if visited[i]==0:
BFS(G,i)
例题
判断一个无向图是不是连通图
#例题
def DFS_1(G,v):
visited[v]=1
for i in range(len(G.adjlist[v])):
w=G.adjlist[v][i].adjvex
if visited[w]==0:
DFS_1(G,w)
def Connext(G):
flag=True
DFS_1(G,0) #传入一个点,进行深度优先遍历,如果一个图是连通的那么它一定会全部遍历得到
for i in range(G.n):
if visited[i]!=0: #如果存在顶点未被访问的话则不连通
flag=False
break
return flag
总结
图的深度优先遍历算法类似于树的先序遍历,宽度优先则类似于层次遍历,深度优先利用递归,广度优先运用队列,熟悉图的基本概念。