假设某个软件工程项目包含n个功能模块。给定每个模块所需要的处理时间为 ti (1≤i≤n) 以及模块之间的依赖关系,比如模块5耗时0.3小时,且必须在模块1和3完成后方可开始处理。模块之间没有循环依赖关系。
(1)若只能顺序处理这些模块,请设计算法给出一种可行的处理顺序来完成该软件工程项目。
(2)若同一时间可以并行处理任意多的模块,请设计算法求出完成该项目的最短时间。
(1)拓扑排序,将任务之间的依赖关系构成一个有向无环图,然后通过拓扑排序获取可行的处理顺序。
算法实现(Python):
def toposort(graph):
in_degrees = dict((u,0) for u in graph) #初始化所有顶点入度为0
vertex_num = len(in_degrees)
for u in graph:
for v in graph[u]:
in_degrees[v] += 1 #计算每个顶点的入度
Q = [u for u in in_degrees if in_degrees[u] == 0] # 筛选入度为0的顶点
Seq = []
while Q:
u = Q.pop() #默认从最后一个删除
Seq.append(u)
for v in graph[u]:
in_degrees[v] -= 1 #移除其所有指向
if in_degrees[v] == 0:
Q.append(v) #再次筛选入度为0的顶点
if len(Seq) == vertex_num:
return Seq
else:
print("there's a circle.")
(2)在拓扑排序的基础上添加前置条件,每个任务的最早完成时间为其最晚前置任务完成时间与自身完成任务需要时间之和,因此可以在拓扑排序的过程中动态更新节点任务完成的最早时间,最后节点中值最大的为所有任务最早完成时间。
算法实现(Python):
def toposort(graph):
in_degrees = dict((u,0) for u in graph) #初始化所有顶点入度为0
vertex_num = len(in_degrees)
time = dict((u,0) for u in graph)
res = dict((u,0) for u in graph)
for u in graph:
time[u] = graph[u][0]
res[u] = graph[u][0]
for v in graph[u][1]:
in_degrees[v] += 1 #计算每个顶点的入度
Q = [u for u in in_degrees if in_degrees[u] == 0] # 筛选入度为0的顶点
Seq = []
while Q:
u = Q.pop() #默认从最后一个删除
Seq.append(u)
for v in graph[u][1]:
in_degrees[v] -= 1 #移除其所有指向
if in_degrees[v] == 0:
Q.append(v) #再次筛选入度为0的顶点
res[v] = max(res[v],res[u]+time[v]) #更新任务的完成时间
print(time)
if len(Seq) == vertex_num:
return max(res[u] for u in res)
else:
return -1