【算法——Python实现】有负权图求单源最短路径BellmanFord算法
来源:互联网 发布:java读取blob字段 编辑:程序博客网 时间:2024/05/18 01:29
class Edge(object): """边""" def __init__(self, a, b, weight): self.a = a # 第一个顶点 self.b = b # 第二个顶点 self.weight = weight # 权值 def v(self): return self.a def w(self): return self.b def wt(self): return self.weight def other(self, x): # 返回x顶点连接的另一个顶点 if x == self.a or x == self.b: if x == self.a: return self.b else: return self.a def __lt__(self, other): # 小于号重载 return self.weight < other.wt() def __le__(self, other): # 小于等于号重载 return self.weight <= other.wt() def __gt__(self, other): # 大于号重载 return self.weight > other.wt() def __ge__(self, other): # 大于等于号重载 return self.weight >= other.wt() def __eq__(self, other): # ==号重载 return self.weight == other.wt()class DenseGraph(object): """有权稠密图 - 邻接矩阵""" def __init__(self, n, directed): self.n = n # 图中的点数 self.m = 0 # 图中的边数 self.directed = directed # bool值,表示是否为有向图 self.g = [[None for _ in range(n)] for _ in range(n)] # 矩阵初始化都为None的二维矩阵 def V(self): # 返回图中点数 return self.n def E(self): # 返回图中边数 return self.m def addEdge(self, v, w, weight): # v和w中增加一条边,v和w都是[0,n-1]区间 if v >= 0 and v < n and w >= 0 and w < n: if self.hasEdge(v, w): self.m -= 1 self.g[v][w] = Edge(v, w, weight) if not self.directed: self.g[w][v] = Edge(w, v, weight) self.m += 1 def hasEdge(self, v, w): # v和w之间是否有边,v和w都是[0,n-1]区间 if v >= 0 and v < n and w >= 0 and w < n: return self.g[v][w] != None class adjIterator(object): """相邻节点迭代器""" def __init__(self, graph, v): self.G = graph # 需要遍历的图 self.v = v # 遍历v节点相邻的边 self.index = 0 # 遍历的索引 def __iter__(self): return self def next(self): while self.index < self.G.V(): # 当索引小于节点数量时遍历,否则为遍历完成,停止迭代 if self.G.g[self.v][self.index]: r = self.G.g[self.v][self.index] self.index += 1 return r self.index += 1 raise StopIteration()class SparseGraph(object): """有权稀疏图- 邻接表""" def __init__(self, n, directed): self.n = n # 图中的点数 self.m = 0 # 图中的边数 self.directed = directed # bool值,表示是否为有向图 self.g = [[] for _ in range(n)] # 矩阵初始化都为空的二维矩阵 def V(self): # 返回图中点数 return self.n def E(self): # 返回图中边数 return self.m def addEdge(self, v, w, weight): # v和w中增加一条边,v和w都是[0,n-1]区间 if v >= 0 and v < n and w >= 0 and w < n: # 考虑到平行边会让时间复杂度变为最差为O(n) # if self.hasEdge(v, w): # return None self.g[v].append(Edge(v, w, weight)) if v != w and not self.directed: self.g[w].append(Edge(w, v, weight)) self.m += 1 def hasEdge(self, v, w): # v和w之间是否有边,v和w都是[0,n-1]区间 # 时间复杂度最差为O(n) if v >= 0 and v < n and w >= 0 and w < n: for i in self.g[v]: if i.other(v) == w: return True return False class adjIterator(object): """相邻节点迭代器""" def __init__(self, graph, v): self.G = graph # 需要遍历的图 self.v = v # 遍历v节点相邻的边 self.index = 0 # 遍历的索引 def __iter__(self): return self def next(self): if len(self.G.g[self.v]): # v有相邻节点才遍历 if self.index < len(self.G.g[self.v]): r = self.G.g[self.v][self.index] self.index += 1 return r else: raise StopIteration() else: raise StopIteration()class ReadGraph(object): """读取文件中的图""" def __init__(self, graph, filename): with open(filename, 'r') as f: line = f.readline() line = line.strip('\n') line = line.split() v = int(line[0]) e = int(line[1]) if v == graph.V(): lines = f.readlines() for i in lines: a, b, w = self.stringstream(i) if a >= 0 and a < v and b >=0 and b < v: graph.addEdge(a, b, w) def stringstream(self, text): result = text.strip('\n') result = result.split() a, b, w = result return int(a), int(b), int(w)class BellmanFord(object): """BellmanFord求单源最短路径,可以有负权值。多次执行松弛操作,一点到一点最短路径最多有V-1条边V个顶点,松弛时超过这个数则证明有负权环,无最短路径 只能处理有向图,无向图如果两个点之间权值都为负会直接形成负权环""" def __init__(self, graph, s): self.G = graph # 图 self.s = s # 原点s self.distTo = [0 for _ in range(self.G.V())] # 从原点到每个节点的权值,初始都为0 self.fromed = [None for _ in range(self.G.V())] # 记录此节点来自哪个节点的连接,存储边。None表示未被访问过 self.hasNegativeCircle = False # 是否有负权环 # BellmanFord # 共对所有顶点做V-1次松弛 for p in range(self.G.V()-1): # 每一轮松弛要对所有节点都做松弛操作 for i in range(self.G.V()): # 只对原点s或者其他已经到达的顶点做松弛操作 if self.fromed[i] or self.s == i: adj = self.G.adjIterator(self.G, i) for e in adj: # 如果w还未被访问过,或经过v的最短路径再到w节点的权值小于w之前被访问时记录的路径,则用经过v再到w的路径替代 if not self.fromed[e.w()] or self.distTo[i] + e.wt() < self.distTo[e.w()]: self.distTo[e.w()] = self.distTo[i] + e.wt() self.fromed[e.w()] = e self.hasNegativeCircle = self.detectNegativeCircle() def detectNegativeCircle(self): # 再做一轮对所有顶点的松弛操作,如果还能松弛则表示有负权环 for i in range(self.G.V()): # 只对原点s或者其他已经到达的顶点做松弛操作 if self.fromed[i] or self.s == i: adj = self.G.adjIterator(self.G, i) for e in adj: # 如果w还未被访问过,或经过v的最短路径再到w节点的权值小于w之前被访问时记录的路径,则表示一定有负权环 if not self.fromed[e.w()] or self.distTo[i] + e.wt() < self.distTo[e.w()]: return True return False def negativeCycle(self): # 查询是否有负权环 return self.hasNegativeCircle def shortestPathTo(self, w): # 从原点到w节点的权值 if not self.hasNegativeCycle and w >= 0 and w < self.G.V(): return self.distTo[w] else: return None def hasPathTo(self, w): # 从原点到w是否有路径 if w >= 0 and w < self.G.V(): return self.fromed[w] != None def shortestPath(self, w): # 从原点到w的最短路径 if not self.hasNegativeCycle and w >= 0 and w < self.G.V(): s = [] e = self.fromed[w] while e: s.append(e) e = self.fromed[e.v()] s.reverse() return s else: return None def showPath(self, w): # 输出路径 if not self.hasNegativeCycle and w >= 0 and w < self.G.V(): s = self.shortestPath(w) i = 0 while i < len(s): print s[i].v() if i == len(s) - 1: print s[i].w() i += 1
阅读全文
0 0
- 【算法——Python实现】有负权图求单源最短路径BellmanFord算法
- 最短路径算法—Dijkstra算法和BellmanFord算法
- 单源最短路径BellmanFord算法实现文件C++
- 单源最短路径算法(BellmanFord算法)
- 单源最短路径(二)————BellmanFord算法
- 算法导论——24.1 BellmanFord算法java实现
- C++实现Bellmanford算法
- BellmanFord 算法
- SPFA:改进的BellmanFord求单源最短路径算法
- 最短路径之 BellmanFord算法
- 单源最短路径BellmanFord算法头文件C++
- 单源最短路径BellmanFord算法主例程C++
- 最短路径之 BellmanFord算法
- 【算法——Python实现】有权图求单源最短路径Dijkstra算法
- POX控制器下bellmanford算法的实现
- 最短路径算法--Dijkstra算法,Bellmanford算法,Floyd算法,Johnson算法
- 6.3.3 最短路径算法--Dijkstra算法,Bellmanford算法,Floyd算法,Johnson算法
- 最短路径算法--Dijkstra算法,Bellmanford算法,Floyd算法,Johnson算法
- MySQL 获得当前日期时间 函数
- Spring Cloud构建微服务架构:服务容错保护(Hystrix依赖隔离)【Dalston版】
- 关于接口和抽象类
- [建站日记]31day—开始构建自己的网站
- 如何在三年内成长为一名技术专家
- 【算法——Python实现】有负权图求单源最短路径BellmanFord算法
- ULTRON 分布式监控系统
- input_file 筛选类型
- CNN的发展历史(LeNet,Alexnet,VGGNet,GoogleNet,ReSNet)
- pureftp的安装和使用
- vc读写扇区资源搜集
- 八皇后问题变种 硅谷AI硕士作业题 One assignment of the MSc in USC
- MYCAT使用篇(2)
- 一个关于php操作进行zip打包的压缩类