Skip to content

Commit c0f129d

Browse files
committed
添加DFS和DFS的应用
1 parent 0dbf6f7 commit c0f129d

File tree

8 files changed

+551
-2
lines changed

8 files changed

+551
-2
lines changed

Diff for: DFS_Application/CycleDetection.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ def hasCycle(self):
162162
CD.get_graph_information()
163163
CD.hasCycle()
164164
print("=======第二种========")
165-
CD2 = CycleDetection_v2("../g.txt")
165+
CD2 = CycleDetection_v2("../g_cycle.txt")
166166
CD2.get_graph_information()
167167
CD2.hasCycle()

Diff for: Graph/stackDFS.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
@author: Alex
3+
@contact: 1272296763@qq.com or jakinmili@gmail.com
4+
@file: stackDFS.py
5+
@time: 2019/10/24 20:09
6+
"""
7+
8+
class Node(object):
9+
def __init__(self, data, next=None):
10+
self.data = data
11+
self.next = next
12+
13+
class Stack(object):
14+
15+
def __init__(self, top = None):
16+
self.top = top
17+
18+
def push(self,data):
19+
#创建新的节点放到栈顶
20+
self.top = Node(data, self.top)
21+
22+
def pop(self):
23+
#拿出栈顶元素,原来的栈发生改变
24+
if self.top is None:
25+
return None
26+
data = self.top.data
27+
self.top = self.top.next
28+
return data
29+
30+
def peek(self):
31+
#查看栈顶元素,原来的栈不变
32+
return self.top.data if self.top is not None else None
33+
34+
def isEmpty(self):
35+
return self.peek() is None
36+
37+
38+
39+
class stackDFS:
40+
41+
def __init__(self, filename):
42+
self.V = 0 # 顶点数
43+
self.E = 0 # 边数
44+
self.adj = None
45+
self.__pre = [] # 深度遍历
46+
with open(filename) as f:
47+
line_num = 0 # 第一行是顶点数和边数
48+
for line in f:
49+
if line_num == 0:
50+
v, e = line.strip().split()
51+
self.V = int(v)
52+
self.E = int(e)
53+
self.adj = [[] for i in range(self.V)] # 创建二维数组即邻接表
54+
else:
55+
# 读取边 写入邻接表
56+
v1, v2 = line.strip().split()
57+
# 转化为整数
58+
v1 = int(v1)
59+
v2 = int(v2)
60+
self.adj[v1].append(v2)
61+
self.adj[v2].append(v1)
62+
line_num += 1
63+
64+
self.__visited = [False for i in range(self.V)]
65+
# 对每个顶点进行遍历
66+
for i in range(self.V):
67+
if self.__visited[i] == False:
68+
self.graph_stack_DFS(i)
69+
70+
71+
def graph_stack_DFS(self, v):
72+
stack = Stack()
73+
74+
75+
# 将v压入栈中,标记v顶点已经访问过
76+
stack.push(v)
77+
self.__visited[v] = True
78+
79+
# 循环遍历取出栈中的元素
80+
while stack.isEmpty() == False:
81+
82+
# 从栈顶取出元素
83+
cur = stack.pop()
84+
self.__pre.append(cur)
85+
86+
# 对cur的相邻的未遍历过的顶点,分别将它们压入栈中,并做标记
87+
for w in self.adj[cur]:
88+
# 查看cur的相邻顶点w是否被遍历过了
89+
if self.__visited[w] == False:
90+
# 此时说明未被遍历过,将w压入栈中
91+
stack.push(w)
92+
# 维护visited数组,标记w已经被访问过
93+
self.__visited[w] = True
94+
95+
def get_dfs_order(self):
96+
print("深度优先遍历(非递归实现):{}".format(self.__pre))
97+
98+
if __name__ == '__main__':
99+
SDFS = stackDFS("../g_ssp.txt")
100+
SDFS.get_dfs_order()

Diff for: Graph_BFS/BFS.py

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
@author: Alex
3+
@contact: 1272296763@qq.com or jakinmili@gmail.com
4+
@file: BFS.py
5+
@time: 2019/10/24 15:51
6+
"""
7+
import queue
8+
class GraphBFS:
9+
10+
def __init__(self, filename):
11+
self.V = 0 # 顶点数
12+
self.E = 0 # 边数
13+
self.adj = None
14+
self.__cccount = 0 # 联通分量
15+
self.__order = [] # 广度优先遍历
16+
with open(filename) as f:
17+
line_num = 0 # 第一行是顶点数和边数
18+
for line in f:
19+
if line_num == 0:
20+
v, e = line.strip().split()
21+
self.V = int(v)
22+
self.E = int(e)
23+
self.adj = [[] for i in range(self.V)] # 创建二维数组即邻接表
24+
else:
25+
# 读取边 写入邻接表
26+
v1, v2 = line.strip().split()
27+
# 转化为整数
28+
v1 = int(v1)
29+
v2 = int(v2)
30+
self.adj[v1].append(v2)
31+
self.adj[v2].append(v1)
32+
line_num += 1
33+
self.graphBFS()
34+
35+
def get_graph_information(self):
36+
"""
37+
打印图的邻接表
38+
:return:
39+
"""
40+
print("V={}, E={}".format(self.V, self.E))
41+
for i, v in enumerate(self.adj):
42+
print("{} : {}".format(i, v))
43+
44+
def validateVertex(self, v):
45+
"""
46+
验证顶点取值
47+
:param v:
48+
:return:
49+
"""
50+
if v<0 or v>=self.V:
51+
raise ValueError("v值超出范围")
52+
53+
def hasEdge(self, v, w):
54+
"""
55+
判断两个顶点是否存在
56+
:param v: 第一个顶点
57+
:param w: 第二个顶点
58+
:return: true or false
59+
"""
60+
self.validateVertex(v)
61+
self.validateVertex(w)
62+
return w in self.adj[v]
63+
64+
def degree(self, v):
65+
"""
66+
求某个顶点的度
67+
:param v:
68+
:return:
69+
"""
70+
self.validateVertex(v)
71+
return len(self.adj[v])
72+
73+
74+
def graphBFS(self):
75+
visited = [False for i in range(self.V)]
76+
order = []
77+
78+
def bfs(v):
79+
# 使用队列来存放经过结点
80+
que = queue.Queue(self.V)
81+
# 经过顶点v时,将v放进队列中
82+
que.put(v)
83+
visited[v] = True
84+
# 队列为空时,即在某个联通分量已经遍历完毕
85+
while que.empty() == False:
86+
# 取出v 并做标记将v放入order 后面开始对v的邻点遍历
87+
v = que.get()
88+
order.append(v)
89+
90+
for w in self.adj[v]:
91+
if visited[w] == False:
92+
que.put(w)
93+
visited[w] = True
94+
95+
for i in range(self.V):
96+
if visited[i] == False:
97+
bfs(i)
98+
self.__order = order
99+
100+
def get_cccount(self):
101+
"""
102+
获取该图的联通分量
103+
:return:
104+
"""
105+
return self.__cccount
106+
107+
def get_BFSorder(self):
108+
"""
109+
获取该图的广度优先搜素
110+
:return:
111+
"""
112+
print("广度优先搜索:{}".format(self.__order))
113+
114+
if __name__ == '__main__':
115+
bfs = GraphBFS("../g.txt")
116+
bfs.get_graph_information()
117+
bfs.get_BFSorder()

Diff for: Graph_BFS/CC.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
@author: Alex
3+
@contact: 1272296763@qq.com or jakinmili@gmail.com
4+
@file: CC.py
5+
@time: 2019/10/24 20:42
6+
"""
7+
import queue
8+
# 联通分量
9+
class CC:
10+
def __init__(self, filename):
11+
self.V = 0 # 顶点数
12+
self.E = 0 # 边数
13+
self.adj = None
14+
self.__cccount = 0 # 联通分量
15+
with open(filename) as f:
16+
line_num = 0 # 第一行是顶点数和边数
17+
for line in f:
18+
if line_num == 0:
19+
v, e = line.strip().split()
20+
self.V = int(v)
21+
self.E = int(e)
22+
self.adj = [[] for i in range(self.V)] # 创建二维数组即邻接表
23+
else:
24+
# 读取边 写入邻接表
25+
v1, v2 = line.strip().split()
26+
# 转化为整数
27+
v1 = int(v1)
28+
v2 = int(v2)
29+
self.adj[v1].append(v2)
30+
self.adj[v2].append(v1)
31+
line_num += 1
32+
33+
self.__visited = [-1 for i in range(self.V)]
34+
# 对每个顶点进行遍历
35+
for i in range(self.V):
36+
if self.__visited[i] == -1:
37+
self.bfs(i, self.__cccount)
38+
self.__cccount += 1
39+
40+
# 非递归
41+
def bfs(self, s, ccid):
42+
que = queue.Queue(self.V)
43+
# 将经过的点放入队列中
44+
que.put(s)
45+
self.__visited[s] = ccid
46+
# 队列为空的时候说明此时已经遍历结束
47+
while que.empty() == False:
48+
# 取出s的相邻顶点v,并对v的相邻顶点w遍历,将遍历过的顶点在visited数组中做标记
49+
v = que.get()
50+
for w in self.adj[v]:
51+
if self.__visited[w] == -1:
52+
que.put(w)
53+
self.__visited[w] = ccid
54+
55+
def get_ccount(self):
56+
print("联通分量大小为:{}".format(self.__cccount))
57+
58+
def get_components(self):
59+
res = [[] for i in range(self.__cccount)]
60+
61+
for i in range(self.V):
62+
res[self.__visited[i]].append(i)
63+
print("各联通分量为:{}".format(res))
64+
65+
if __name__ == '__main__':
66+
cc = CC("../g_ssp.txt")
67+
cc.get_ccount()
68+
cc.get_components()

Diff for: Graph_BFS/CycleDetection.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
@author: Alex
3+
@contact: 1272296763@qq.com or jakinmili@gmail.com
4+
@file: CycleDetection.py
5+
@time: 2019/10/24 21:18
6+
"""
7+
import queue
8+
class CycleDetection:
9+
10+
def __init__(self, filename):
11+
self.V = 0 # 顶点数
12+
self.E = 0 # 边数
13+
self.adj = None
14+
with open(filename) as f:
15+
line_num = 0 # 第一行是顶点数和边数
16+
for line in f:
17+
if line_num == 0:
18+
v, e = line.strip().split()
19+
self.V = int(v)
20+
self.E = int(e)
21+
self.adj = [[] for i in range(self.V)] # 创建二维数组即邻接表
22+
else:
23+
# 读取边 写入邻接表
24+
v1, v2 = line.strip().split()
25+
# 转化为整数
26+
v1 = int(v1)
27+
v2 = int(v2)
28+
self.adj[v1].append(v2)
29+
self.adj[v2].append(v1)
30+
line_num += 1
31+
32+
self.visited = [False for i in range(self.V)]
33+
self.pre = [-1 for i in range(self.V)] # 记录每一个结点的父亲结点即上一个结点
34+
self.hasCycle = False
35+
36+
# 对每一个结点都进行遍历
37+
for v in range(self.V):
38+
# 若该结点为未被访问过,即二部图的情况
39+
if self.visited[v] == False:
40+
if self.bfs(v) == True:
41+
self.hasCycle = True
42+
break
43+
44+
45+
def bfs(self, s):
46+
que = queue.Queue(self.V)
47+
que.put(s)
48+
self.visited[s] = True
49+
self.pre[s] = s
50+
51+
while que.empty() == False:
52+
v = que.get()
53+
54+
# 将v的每一个未访问的相邻结点w都压入队列
55+
for w in self.adj[v]:
56+
if self.visited[w] == False:
57+
que.put(w)
58+
self.visited[w] = True
59+
self.pre[w] = v
60+
elif self.pre[v] != w:
61+
# 此处是检测环的关键,如果w被访问过了,要检测w是不是上一个结点v,如果不是,则有环
62+
return True
63+
64+
def get_hasCycle(self):
65+
return self.hasCycle
66+
if __name__ == '__main__':
67+
cd = CycleDetection("../g_cycle.txt")
68+
print(cd.get_hasCycle())

0 commit comments

Comments
 (0)