深度优先搜索算法
介绍
深度优先搜索(DFS, Depth First Search)是一个针对图和树的遍历算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。
执行顺序
- 先选出A开始
- 看A可以到达的是B,C stack = B,C
- 选择到达C,C可以到达的是A,B,D,E,其中A,B已经遇见过可选,D,E stack = B,D,E
- 选择E,E可以达到C,D,都已经遇见stack= B,D
- 后退到D,可以到达B,C,E,F,其中B,C,E都见过选择F,stack = B
- 后退到B,这样全部都被搜寻过了
程序示例
运行思路的程序
graph = {
"A" : ["B", "C"],
"B" : ["A", "C", "D"],
"C" : ["A", "B", "D", "E"],
"D" : ["B", "C", "E", "F"],
"E" : ["C", "D"],
"F" : ["D"]
}
'''
A
/ \
B---C
\ / \
D---E
/
F
step1:A
stack = B C
sen = A
already = A
step2:C
stack = B D E
sen = A B C D E
already = A C
step3:E
stack = B D
sen = A B C D E
already = A C E
step4:E
stack = B F
sen = A B C D E F
already = A C E D
'''
def DFS(graph, startNode):
stack = []
already = []
stack.append(startNode)
seen = set()
seen.add(startNode)
while (len(stack) > 0):
vertex = stack.pop()
already.append(vertex)
print(vertex)
nodes = graph[vertex]
for w in nodes:
if w not in seen:
stack.append(w)
seen.add(w)
print('stack',stack)
print('seen',seen)
DFS(graph, "A")
全路径搜索
# DFS
graph = {
"A" : ["B", "C"],
"B" : ["A", "C", "D"],
"C" : ["A", "B", "D", "E"],
"D" : ["B", "C", "E", "F"],
"E" : ["C", "D"],
"F" : ["D"]
}
'''
A
/ \
B---C
\ / \
D---E
/
F
step1:A
stack = B C
sen = A
already = A
step2:C
stack = B D E
sen = A B C D E
already = A C
step3:E
stack = B D
sen = A B C D E
already = A C E
step4:D
stack = B F
sen = A B C D E F
already = A C E D
step5:F
stack = B
sen = A B C D E F
already = A C E D F
step5:B
stack =
sen = A B C D E F
already = A C E D F B
'''
def DFS(graph, startNode):
global stack
global seen
print("stack",stack)
#print("seen",seen)
nodes = graph[startNode]
for w in nodes:
if w not in seen:
stack.append(w)
seen.append(w)
DFS(graph, w)
seen.pop()
stack.pop()
global stack
stack = []
global seen
seen = []
stack.append("A")
seen.append("A")
DFS(graph, "A")
stack ['A']
stack ['A', 'B']
stack ['A', 'B', 'C']
stack ['A', 'B', 'C', 'D']
stack ['A', 'B', 'C', 'D', 'E']
stack ['A', 'B', 'C', 'D', 'F']
stack ['A', 'B', 'C', 'E']
stack ['A', 'B', 'C', 'E', 'D']
stack ['A', 'B', 'C', 'E', 'D', 'F']
stack ['A', 'B', 'D']
stack ['A', 'B', 'D', 'C']
stack ['A', 'B', 'D', 'C', 'E']
stack ['A', 'B', 'D', 'E']
stack ['A', 'B', 'D', 'E', 'C']
stack ['A', 'B', 'D', 'F']
stack ['A', 'C']
stack ['A', 'C', 'B']
stack ['A', 'C', 'B', 'D']
stack ['A', 'C', 'B', 'D', 'E']
stack ['A', 'C', 'B', 'D', 'F']
stack ['A', 'C', 'D']
stack ['A', 'C', 'D', 'B']
stack ['A', 'C', 'D', 'E']
stack ['A', 'C', 'D', 'F']
stack ['A', 'C', 'E']
stack ['A', 'C', 'E', 'D']
stack ['A', 'C', 'E', 'D', 'B']
stack ['A', 'C', 'E', 'D', 'F']
循环实现DFS
递归的实现方法可能会降低程序的效率,这里就该写为循环的样子,但是这种方法只能进入到固定的深度。
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, startNode):
stack = []
stack1 = []
stack2 = []
stack3 = []
stack4 = []
already = []
path = []
stack.append(startNode)
seen = set()
seen.add(startNode)
if (len(stack) > 0):
vertex = stack.pop()
path.append(vertex)
nodes = graph[vertex]
for w in nodes:
if w not in path:
stack.append(w)
print("path",path)
while len(stack) > 0:
vertex = stack.pop()
path.append(vertex)
nodes = graph[vertex]
for w in nodes:
if w not in path:
stack1.append(w)
print("path",path)
while len(stack1) > 0:
vertex = stack1.pop()
path.append(vertex)
nodes = graph[vertex]
for w in nodes:
if w not in path:
stack2.append(w)
print("path",path)
while len(stack2) > 0:
vertex = stack2.pop()
path.append(vertex)
nodes = graph[vertex]
for w in nodes:
if w not in path:
stack3.append(w)
print("path",path)
while len(stack3) > 0:
vertex = stack3.pop()
path.append(vertex)
nodes = graph[vertex]
for w in nodes:
if w not in path:
stack4.append(w)
print("path",path)
path.pop()
path.pop()
path.pop()
path.pop()
DFS(graph, "A")