图的分类
存图方式
1.邻接矩阵
空间复杂度一般为n*n一般不用。
2.邻接表(主要)
3.链式前向星(主要)
无向图的存储相比右向图,需要双向加边。
图的遍历
一、DFS(深度优先搜索)
遍历思想:基本思想:首先从图中某个顶点v0出发,访问此顶点,然后依次从v相邻的顶点出发深度优先遍历,直至图中所有与v路径相通的顶点都被访问了;若此时尚有顶点未被访问,则从中选一个顶点作为起始点,重复上述过程,直到所有的顶点都被访问。
深度优先遍历用递归实现比较简单,只需用一个递归方法来遍历所有顶点,在访问某一个顶点时:
1.将它标为已访问
2.递归的访问它的所有未被标记过的邻接点
#深度优先遍历
graph = {"A":["B","C"],
"B":["A","C","D"],
"C":["A","B","D","E"],
"D":["B","C","E","F"],
"E":["C","D"],
"F":["D"],
} #用一个字典保存图
def DFS(graph,s): #s代表起始点
stack=[] #用数组代替一个栈
stack.append(s)
seen=set() #集合,存储已经访问过的节点
seen.add(s)
while (len(stack)>0):
vertex=stack.pop() #数组pop()去掉0,弹出最后一个元素,类似栈
nodes=graph[vertex]
for i in nodes:
if i not in seen:
stack.append(i)
seen.add(i)
print(vertex)
DFS(graph,"A")
二、BFS(广度优先搜索)
**遍历思想:**首先,从图的某个顶点v0出发,访问了v0之后,依次访问与v0相邻的未被访问的顶点,然后分别从这些顶点出发,广度优先遍历,直至所有的顶点都被访问完。
#广度优先遍历
graph = {"A":["B","C"],
"B":["A","C","D"],
"C":["A","B","D","E"],
"D":["B","C","E","F"],
"E":["C","D"],
"F":["D"],
} #用一个字典保存图
def BFS(graph,s): #s代表起始点
queue=[] #用数组代替一个队列
queue.append(s)
seen=set() #集合,存储已经访问过的节点
seen.add(s)
while (len(queue)>0):
vertex=queue.pop(0)
nodes=graph[vertex]
for i in nodes:
if i not in seen:
queue.append(i)
seen.add(i)
print(vertex)
BFS(graph,"F")
有权图的最短路径
可以由** [优先队列]**解决 链接:(https://www.jianshu.com/p/b51ab28ca8dd).
对下图进行操作:
首先将A放入队列中,A到A的距离为0,将拿出,再同时放入B、C,因为(B,5)的优先级低于(C,1),交换B、C的顺序。再将C拿出,在插入C的邻接点D、E,此时他们的优先级分别为(D,5),(E,9).后面数字分别为A到D、E的距离
最终得到如下:
代码实现过程如下:(以A为起始点)
import heapq #优先队列
import math
#heapq.heappush(pqueue,(1,'A'))#A的权限是1
graph = {"A":{"B":5,"C":1},
"B":{"A":5,"C":2,"D":1},
"C":{"A":1,"B":2,"D":4,"E":8},
"D":{"B":1,"C":4,"E":3,"F":6},
"E":{"C":8,"D":3},
"F":{"D":6}
}
def init_distance(graph,s):
distance={s:0}
for vertex in graph:
if vertex != s:
distance[vertex]=math.inf
return distance
def dijkstra(graph,s): #s代表起始点
pqueue=[] #用数组代替一个队列
heapq.heappush(pqueue,(0,s))#A的权限是1
seen=set() #集合,存储已经访问过的节点
parent={s:None} #保存上一个节点
distance=init_distance(graph,s) #初始化距离
#将第一个距离设为0,同时把其他的设为正无穷 init_distance
while (len(pqueue)>0):
pair=heapq.heappop(pqueue)#有两个内容
dist=pair[0]
vertex=pair[1]
seen.add(vertex) #拿出来后才确定该节点被访问过
nodes=graph[vertex].keys()
for i in nodes:
if i not in seen:
if dist + graph[vertex][i]<distance[i]:
heapq.heappush(pqueue,(dist+graph[vertex][i],i))
#如过没有出现,需要计算距离
parent[i]=vertex
distance[i]=dist+graph[vertex][i]
return parent,distance
parent,distance=dijkstra(graph,"A")
print(parent)
print(distance)
输出结果如下:
与分析结果一致。