Table of contents
breadth first traversal
First traverse the nodes adjacent to the current node, then traverse the nodes one layer deeper, and proceed layer by layer until a suitable result is found.
ABCDEFGHIJK and ABCDEF
Features: When solving problems, in most cases, it is not necessary to traverse the entire graph.
Implementation method: queue.
Application: Find the shortest path in an unweighted graph.
Traverse steps:
1. Define an operation queue Que, an array Arr that records the scanned nodes, and an array res of the traversed results.
2. Given the start node start, enqueue the start node and add it to the array Arr.
3. Perform a scan (as long as the queue is not empty):
Dequeue operation, and update the dequeue node v to the new starting node start.
Scan the nodes adjacent (connected) to the starting node start, and judge whether they have been scanned through the Arr array:
If scanned, continue.
If not, enqueue and join the array Arr.
The currently dequeued node v is added to the result array res.
Depth-first traversal
One road goes to the dark, and if it fails, go back to the previous fork until the whole map is completed.
ABDHIEJCFGK and ABDFEC
Features: When solving a problem, it is necessary to traverse the entire graph.
Implementation method: stack.
Application: How many solutions are there, how many paths are there, the maximum path and similar problems.
Traverse steps:
1. Define an operation stack stack, an array Arr that records the scanned nodes, and an array res of the traversed results.
2. Given the start node start, execute the start node into the stack and add it to the array Arr.
3. Perform a scan (as long as the stack is not empty):
Pop out operation, and update the pop-up node v to the new starting node start.
Scan the nodes adjacent (connected) to the starting node start, and judge whether they have been scanned through the Arr array:
If scanned, continue.
If not, it is pushed onto the stack and added to the array Arr.
The currently popped node v is added to the result array res.
Note: BFS and DFS may not have a unique path when traversing the search
Such as DFS:
python code
breadth first traversal
# 构造图
graph = {"A": ['B', 'C'],
"B": ['A', 'C', 'D'],
"C": ['A', 'B', 'D', 'E'],
"D": ['B', 'C', 'E', 'F'],
"E": ['C', 'D'],
"F": ['D']}
# graph图结构,start_v起始结点
def BFS(graph, start_v):
queue = [] # 队列
check = set() # 已经访问过
queue.append(start_v) # 放入起始结点
check.add(start_v) # 放入起始结点
# 遍历访问图
while len(queue) > 0:
vertex = queue.pop(0)
nodes = graph[vertex]
# 从当前结点相连接的结点中寻找
for v in nodes:
# 判断是否已经访问过,没有则访问
if v not in check:
queue.append(v)
check.add(v)
print(vertex) # 依次访问的节点
if __name__=="__main__":
# 宽度优先遍历
BFS(graph, 'A')
Depth-first traversal
# 构造图
graph = {"A": ['B', 'C'],
"B": ['A', 'C', 'D'],
"C": ['A', 'B', 'D', 'E'],
"D": ['B', 'C', 'E', 'F'],
"E": ['C', 'D'],
"F": ['D']}
# graph图结构,start_v起始结点
def DFS(graph, start_v):
stack = [] # 栈
check = set() # 已经访问过
stack.append(start_v) # 放入起始结点
check.add(start_v) # 放入起始结点
# 遍历访问图
while len(stack) > 0:
vertex = stack.pop()
nodes = graph[vertex]
# 从当前结点相连接的结点中寻找
for v in nodes:
# 判断是否已经访问过,没有则访问
if v not in check:
stack.append(v)
check.add(v)
print(vertex) # 依次访问的节点
if __name__=="__main__":
# 深度优先遍历
DFS(graph, 'A')
expand
Save the parent node
Find the shortest distance (from the current node to the starting node)
graph = {"A": ['B', 'C'],
"B": ['A', 'C', 'D'],
"C": ['A', 'B', 'D', 'E'],
"D": ['B', 'C', 'E', 'F'],
"E": ['C', 'D'],
"F": ['D']}
# 记录父节点,求最短路径(距离)
def BFSsuper(graph, start_v):
queue = [] # 队列
check = set() # 已经访问过
parent = {start_v: None} # 记录父节点
queue.append(start_v) # 放入起始结点
check.add(start_v) # 放入起始结点
# 遍历访问图
while len(queue) > 0:
vertex = queue.pop(0)
nodes = graph[vertex]
# 从当前结点相连接的结点中寻找
for v in nodes:
# 判断是否已经访问过,没有则访问
if v not in check:
queue.append(v)
check.add(v)
parent[v] = vertex
#print(vertex) # 依次访问的节点
# 返回父结点
return parent
if __name__=="__main__":
# 扩展(记录父节点)
start_v = 'A'
parent = BFSsuper(graph, start_v)
print('-----')
print("结点", "父结点")
for key in parent:
print(key, parent[key])
print('-----')
# 求最短路径(距离),从一个节点到遍历的初始节点的路径,通过父节点查找,直到触顶结束
node_start = 'E'
print("结点{}到起始结点{}的最短路径为:" .format(node_start, start_v))
while node_start != None:
print(node_start, end=", ")
node_start = parent[node_start]
weighted graph
dijkstra's algorithm
import math
import heapq
weightedGrah = {"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, stat_v):
distance = {stat_v: 0} # 起始点距离标为0
# 其它点距离标为正无穷
for vertex in graph:
if vertex != stat_v:
distance[vertex] = math.inf
return distance
# 加权图,dijkstra算法,求最短路径(距离)
def dijkstra(graph, start_v):
# 创建优先队列
pqueue = []
heapq.heappush(pqueue, (0, start_v))
check = set() # 已经访问过
parent = {start_v: None} # 记录父节点
distance = init_distance(graph, start_v) # 统计当前结点到起始结点的距离
while len(pqueue) > 0:
pair = heapq.heappop(pqueue)
dist = pair[0]
vertex = pair[1]
check.add(vertex)
nodes = graph[vertex].keys()
for v in nodes:
if v not in check:
# 确保最短距离
if dist+graph[vertex][v] < distance[v]:
heapq.heappush(pqueue, (dist+graph[vertex][v], v))
parent[v] = vertex
distance[v] = dist+graph[vertex][v]
return parent, distance
if __name__=="__main__":
# 加权图
parent, distance = dijkstra(weightedGrah, 'A')
#print(parent)
print(distance)