【算法——Python实现】有权图求最小生成树LazyPrim算法
来源:互联网 发布:淘宝衣服质检报告 编辑:程序博客网 时间:2024/06/03 11:16
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), float(w)class MinHeap(object): """最小堆""" def __init__(self): self.data = [] # 创建堆 self.count = len(self.data) # 元素数量 # def __init__(self, arr): # self.data = copy.copy(arr) # self.count = len(self.data) # i = self.count / 2 # while i >= 1: # self.shiftDown(i) # i -= 1 def size(self): return self.count def isEmpty(self): return self.count == 0 def insert(self, item): # 插入元素入堆 self.data.append(item) self.count += 1 self.shiftup(self.count) def shiftup(self, count): # 将插入的元素放到合适位置,保持最小堆 while count > 1 and self.data[(count/2)-1] > self.data[count-1]: self.data[(count/2)-1], self.data[count-1] = self.data[count-1], self.data[(count/2)-1] count /= 2 def extractMin(self): # 出堆 if self.count > 0: ret = self.data[0] self.data[0], self.data[self.count-1] = self.data[self.count-1], self.data[0] self.data.pop() self.count -= 1 self.shiftDown(1) return ret def shiftDown(self, count): # 将堆的索引位置元素向下移动到合适位置,保持最小堆 while 2 * count <= self.count : # 证明有孩子 j = 2 * count if j + 1 <= self.count: # 证明有右孩子 if self.data[j] < self.data[j-1]: j += 1 if self.data[count-1] <= self.data[j-1]: # 堆的索引位置已经小于两个孩子节点,不需要交换了 break self.data[count-1], self.data[j-1] = self.data[j-1], self.data[count-1] count = jclass LazyPrimMST(object): """最小生成树T,每次选取横切边中权值最小的边,将另一端顶点加入树中""" def __init__(self, graph): self.G = graph # 传入图 self.pq = MinHeap() # 最小堆,用于选择权值最小的边 self.marked = [False for _ in range(self.G.V())] # 用于标记已经被选取为树的节点,初始都为False self.mst = [] # 记录被选取的边 self.mstWeight = 0 # 记录最小生成树的总权值 # Lizy Prim self.visit(0) while not self.pq.isEmpty(): # 取出权值最小的横切边 e = self.pq.extractMin() if self.marked[e.v()] == self.marked[e.w()]: # 如果e不是横切边(比如两个顶点都已经加入树中) continue # 选取e这条边,组成最小生成树 self.mst.append(e) # 此时e边两个顶点必有一个未加入树中 if not self.marked[e.v()]: self.visit(e.v()) else: self.visit(e.w()) self.mstWeight = sum([i.wt() for i in self.mst]) def visit(self, v): # 访问 if not self.marked[v]: # self.marked[v]为False,表示该节点还未被加入树中 self.marked[v] = True adj = self.G.adjIterator(self.G, v) for i in adj: if not self.marked[i.other(v)]: # 与v相连接的另一端还未被加入树中,则这一条边为横切边,加入到最小堆中 # 此处Edge类重载运算符,可直接放入堆中进行计算 self.pq.insert(i) def mstEdges(self): # 查询最小生成树的边 return self.mst def result(self): # 返回最小生成树的权值 return self.mstWeight
阅读全文
0 0
- 【算法——Python实现】有权图求最小生成树LazyPrim算法
- 【算法——Python实现】有权图求最小生成树Prim算法
- 【算法——Python实现】有权图求最小生成树Kruskal算法
- java编写Prim算法实现最小生成树(LazyPrim算法的优化版)
- 数据结构与算法分析(Java语言描述)(31)—— 使用 Prim 算法求有权图的最小生成树(MST)
- 数据结构与算法分析(Java语言描述)(32)—— 使用 Kruskal 算法求有权图的最小生成树
- 【算法——Python实现】有权图求单源最短路径Dijkstra算法
- KRUSCAL算法求图的最小生成树(C实现)
- 求图的最小生成树之--Prim算法实现
- 实现Kruskal算法,求图的最小生成树。
- python实现prim 最小生成树算法
- 图-有权图-最小生成树
- 最小生成树算法——Kruskal算法Java实现
- Prim算法求最小生成树的c++代码实现
- Kruskal算法求最小生成树的c++代码实现
- 最小生成树算法—kcruscal算法
- 求无向连通图的最小生成树算法——Prim与Kruska
- Prim算法——求无向图的最小生成树
- confluence上传文件附件预览乱码问题
- Hadoop概念学习系列之Hadoop、Spark学习路线(很值得推荐)(十八)
- vue饿了么
- 2017-10-20课堂代码
- If 条件控制 & while循环语句
- 【算法——Python实现】有权图求最小生成树LazyPrim算法
- 洛谷八连测string
- iOS 指纹认证登陆开发(TouchID)
- c语言中,求1到n的阶乘之和
- PyQt5+python3+pycharm开发环境配置
- 3种机器学习算法
- mysql 建立索引的原则
- gitlab安装和迁库
- deep learning---利用caffe在vgg-face上finetuing自己的人脸数据