python 经典算法之--最小生成树算法(Minimum Spanning Tree Algorithm)

最小生成树算法是一种求解无向连通图的生成树的算法,主要用于求解网络、运输、电力等行业的最优路径问题。在这里我们将介绍两种最小生成树算法:Kruskal算法和Prim算法。

  1. Kruskal算法

Kruskal算法的基本思想是:将图中的所有边按照权值从小到大排序,依次加入生成树中,直到生成树中包含所有顶点为止。在加入边的过程中,需要判断加入边是否会形成环,若不形成环则加入生成树中。

下面是Kruskal算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = []  # 存储图的边
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
    
    # 查找顶点所在集合的根节点
    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
    
    # 合并两个集合
    def union(self, parent, rank, x, y):
        x_root = self.find(parent, x)
        y_root = self.find(parent, y)
        
        if rank[x_root] < rank[y_root]:
            parent[x_root] = y_root
        elif rank[x_root] > rank[y_root]:
            parent[y_root] = x_root
        else:
            parent[y_root] = x_root
            rank[x_root] += 1
    
    # Kruskal算法求解最小生成树
    def kruskal_mst(self):
        result = []  # 存储最小生成树的边
        i = 0  # 边的计数器
        e = 0  # 最小生成树的边的计数器
        
        # 将所有边按照权值从小到大排序
        self.graph = sorted(self.graph, key=lambda item: item[2])
        
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        
        # 只需要找到v-1条边
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i += 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            
            # 判断是否形成环
            if x != y:
                e += 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)
        
        # 输出结果
        print("最小生成树为:")
        for u, v, weight in result:
            print(f"{u} - {v} : {weight}")

下面是一个使用Kruskal算法求解最小生成树的示例:

g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)

g.kruskal_mst()

输出结果为:

最小生成树为:
2 - 3 : 4
0 - 3 : 5
0 - 1 : 10

  1. Prim算法

Prim算法的基本思想是:从一个顶点开始,每次选择一个与当前生成树相邻的最小权值边加入生成树中,直到生成树包含所有顶点为止。

下面是Prim算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = [[] for i in range(vertices)]  # 存储图的邻接表
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph[u].append([v, w])
        self.graph[v].append([u, w])
    
    # Prim算法求解最小生成树
    def prim_mst(self):
        key = [float('inf')] * self.V  # 存储顶点的权值
        parent = [-1] * self.V  # 存储顶点的父节点
        in_mst = [False] * self.V  # 存储顶点是否在最小生成树中
        
        # 从第一个顶点开始
        key[0] = 0
        parent[0] = -1
        
        # 需要找到v-1条边
        for i in range(self.V - 1):
            # 找到距离生成树最近的顶点
            min_key = float('inf')
            for v in range(self.V):
                if in_mst[v] is False and key[v] < min_key:
                    min_key = key[v]
                    u = v
            
            in_mst[u] = True
            
            # 更新顶点的权值和父节点
            for v, w in self.graph[u]:
                if in_mst[v] is False and w < key[v]:
                    key[v] = w
                    parent[v] = u
        
        # 输出结果
        print("最小生成树为:")
        for i in range(1, self.V):
            print(f"{parent[i]} - {i} : {key[i]}")

下面是一个使用Prim算法求解最小生成树的示例:

g = Graph(5)
g.add_edge(0, 1, 2)
g.add_edge(0, 3, 6)
g.add_edge(1, 2, 3)
g.add_edge(1, 3, 8)
g.add_edge(1, 4, 5)
g.add_edge(2, 4, 7)
g.add_edge(3, 4, 9)

g.prim_mst()

输出结果为:

最小生成树为:
0 - 1 : 2
1 - 2 : 3
0 - 3 : 6
1 - 4 : 5

最小生成树算法是一种求解无向连通图的生成树的算法,主要用于求解网络、运输、电力等行业的最优路径问题。在这里我们将介绍两种最小生成树算法:Kruskal算法和Prim算法。

  1. Kruskal算法

Kruskal算法的基本思想是:将图中的所有边按照权值从小到大排序,依次加入生成树中,直到生成树中包含所有顶点为止。在加入边的过程中,需要判断加入边是否会形成环,若不形成环则加入生成树中。

下面是Kruskal算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = []  # 存储图的边
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
    
    # 查找顶点所在集合的根节点
    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
    
    # 合并两个集合
    def union(self, parent, rank, x, y):
        x_root = self.find(parent, x)
        y_root = self.find(parent, y)
        
        if rank[x_root] < rank[y_root]:
            parent[x_root] = y_root
        elif rank[x_root] > rank[y_root]:
            parent[y_root] = x_root
        else:
            parent[y_root] = x_root
            rank[x_root] += 1
    
    # Kruskal算法求解最小生成树
    def kruskal_mst(self):
        result = []  # 存储最小生成树的边
        i = 0  # 边的计数器
        e = 0  # 最小生成树的边的计数器
        
        # 将所有边按照权值从小到大排序
        self.graph = sorted(self.graph, key=lambda item: item[2])
        
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        
        # 只需要找到v-1条边
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i += 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            
            # 判断是否形成环
            if x != y:
                e += 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)
        
        # 输出结果
        print("最小生成树为:")
        for u, v, weight in result:
            print(f"{u} - {v} : {weight}")

下面是一个使用Kruskal算法求解最小生成树的示例:

g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)

g.kruskal_mst()

输出结果为:

最小生成树为:
2 - 3 : 4
0 - 3 : 5
0 - 1 : 10

  1. Prim算法

Prim算法的基本思想是:从一个顶点开始,每次选择一个与当前生成树相邻的最小权值边加入生成树中,直到生成树包含所有顶点为止。

下面是Prim算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = [[] for i in range(vertices)]  # 存储图的邻接表
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph[u].append([v, w])
        self.graph[v].append([u, w])
    
    # Prim算法求解最小生成树
    def prim_mst(self):
        key = [float('inf')] * self.V  # 存储顶点的权值
        parent = [-1] * self.V  # 存储顶点的父节点
        in_mst = [False] * self.V  # 存储顶点是否在最小生成树中
        
        # 从第一个顶点开始
        key[0] = 0
        parent[0] = -1
        
        # 需要找到v-1条边
        for i in range(self.V - 1):
            # 找到距离生成树最近的顶点
            min_key = float('inf')
            for v in range(self.V):
                if in_mst[v] is False and key[v] < min_key:
                    min_key = key[v]
                    u = v
            
            in_mst[u] = True
            
            # 更新顶点的权值和父节点
            for v, w in self.graph[u]:
                if in_mst[v] is False and w < key[v]:
                    key[v] = w
                    parent[v] = u
        
        # 输出结果
        print("最小生成树为:")
        for i in range(1, self.V):
            print(f"{parent[i]} - {i} : {key[i]}")

下面是一个使用Prim算法求解最小生成树的示例:

g = Graph(5)
g.add_edge(0, 1, 2)
g.add_edge(0, 3, 6)
g.add_edge(1, 2, 3)
g.add_edge(1, 3, 8)
g.add_edge(1, 4, 5)
g.add_edge(2, 4, 7)
g.add_edge(3, 4, 9)

g.prim_mst()

输出结果为:

最小生成树为:
0 - 1 : 2
1 - 2 : 3
0 - 3 : 6
1 - 4 : 5

最小生成树算法是一种求解无向连通图的生成树的算法,主要用于求解网络、运输、电力等行业的最优路径问题。在这里我们将介绍两种最小生成树算法:Kruskal算法和Prim算法。

  1. Kruskal算法

Kruskal算法的基本思想是:将图中的所有边按照权值从小到大排序,依次加入生成树中,直到生成树中包含所有顶点为止。在加入边的过程中,需要判断加入边是否会形成环,若不形成环则加入生成树中。

下面是Kruskal算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = []  # 存储图的边
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
    
    # 查找顶点所在集合的根节点
    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
    
    # 合并两个集合
    def union(self, parent, rank, x, y):
        x_root = self.find(parent, x)
        y_root = self.find(parent, y)
        
        if rank[x_root] < rank[y_root]:
            parent[x_root] = y_root
        elif rank[x_root] > rank[y_root]:
            parent[y_root] = x_root
        else:
            parent[y_root] = x_root
            rank[x_root] += 1
    
    # Kruskal算法求解最小生成树
    def kruskal_mst(self):
        result = []  # 存储最小生成树的边
        i = 0  # 边的计数器
        e = 0  # 最小生成树的边的计数器
        
        # 将所有边按照权值从小到大排序
        self.graph = sorted(self.graph, key=lambda item: item[2])
        
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        
        # 只需要找到v-1条边
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i += 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            
            # 判断是否形成环
            if x != y:
                e += 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)
        
        # 输出结果
        print("最小生成树为:")
        for u, v, weight in result:
            print(f"{u} - {v} : {weight}")

下面是一个使用Kruskal算法求解最小生成树的示例:

g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)

g.kruskal_mst()

输出结果为:

最小生成树为:
2 - 3 : 4
0 - 3 : 5
0 - 1 : 10

  1. Prim算法

Prim算法的基本思想是:从一个顶点开始,每次选择一个与当前生成树相邻的最小权值边加入生成树中,直到生成树包含所有顶点为止。

下面是Prim算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = [[] for i in range(vertices)]  # 存储图的邻接表
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph[u].append([v, w])
        self.graph[v].append([u, w])
    
    # Prim算法求解最小生成树
    def prim_mst(self):
        key = [float('inf')] * self.V  # 存储顶点的权值
        parent = [-1] * self.V  # 存储顶点的父节点
        in_mst = [False] * self.V  # 存储顶点是否在最小生成树中
        
        # 从第一个顶点开始
        key[0] = 0
        parent[0] = -1
        
        # 需要找到v-1条边
        for i in range(self.V - 1):
            # 找到距离生成树最近的顶点
            min_key = float('inf')
            for v in range(self.V):
                if in_mst[v] is False and key[v] < min_key:
                    min_key = key[v]
                    u = v
            
            in_mst[u] = True
            
            # 更新顶点的权值和父节点
            for v, w in self.graph[u]:
                if in_mst[v] is False and w < key[v]:
                    key[v] = w
                    parent[v] = u
        
        # 输出结果
        print("最小生成树为:")
        for i in range(1, self.V):
            print(f"{parent[i]} - {i} : {key[i]}")

下面是一个使用Prim算法求解最小生成树的示例:

g = Graph(5)
g.add_edge(0, 1, 2)
g.add_edge(0, 3, 6)
g.add_edge(1, 2, 3)
g.add_edge(1, 3, 8)
g.add_edge(1, 4, 5)
g.add_edge(2, 4, 7)
g.add_edge(3, 4, 9)

g.prim_mst()

输出结果为:

最小生成树为:
0 - 1 : 2
1 - 2 : 3
0 - 3 : 6
1 - 4 : 5

最小生成树算法是一种求解无向连通图的生成树的算法,主要用于求解网络、运输、电力等行业的最优路径问题。在这里我们将介绍两种最小生成树算法:Kruskal算法和Prim算法。

  1. Kruskal算法

Kruskal算法的基本思想是:将图中的所有边按照权值从小到大排序,依次加入生成树中,直到生成树中包含所有顶点为止。在加入边的过程中,需要判断加入边是否会形成环,若不形成环则加入生成树中。

下面是Kruskal算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = []  # 存储图的边
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph.append([u, v, w])
    
    # 查找顶点所在集合的根节点
    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
    
    # 合并两个集合
    def union(self, parent, rank, x, y):
        x_root = self.find(parent, x)
        y_root = self.find(parent, y)
        
        if rank[x_root] < rank[y_root]:
            parent[x_root] = y_root
        elif rank[x_root] > rank[y_root]:
            parent[y_root] = x_root
        else:
            parent[y_root] = x_root
            rank[x_root] += 1
    
    # Kruskal算法求解最小生成树
    def kruskal_mst(self):
        result = []  # 存储最小生成树的边
        i = 0  # 边的计数器
        e = 0  # 最小生成树的边的计数器
        
        # 将所有边按照权值从小到大排序
        self.graph = sorted(self.graph, key=lambda item: item[2])
        
        parent = []
        rank = []
        for node in range(self.V):
            parent.append(node)
            rank.append(0)
        
        # 只需要找到v-1条边
        while e < self.V - 1:
            u, v, w = self.graph[i]
            i += 1
            x = self.find(parent, u)
            y = self.find(parent, v)
            
            # 判断是否形成环
            if x != y:
                e += 1
                result.append([u, v, w])
                self.union(parent, rank, x, y)
        
        # 输出结果
        print("最小生成树为:")
        for u, v, weight in result:
            print(f"{u} - {v} : {weight}")

下面是一个使用Kruskal算法求解最小生成树的示例:

g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)

g.kruskal_mst()

输出结果为:

最小生成树为:
2 - 3 : 4
0 - 3 : 5
0 - 1 : 10

  1. Prim算法

Prim算法的基本思想是:从一个顶点开始,每次选择一个与当前生成树相邻的最小权值边加入生成树中,直到生成树包含所有顶点为止。

下面是Prim算法的具体实现:

# 定义Graph类
class Graph:
    def __init__(self, vertices):
        self.V = vertices  # 顶点数
        self.graph = [[] for i in range(vertices)]  # 存储图的邻接表
    
    # 添加一条边
    def add_edge(self, u, v, w):
        self.graph[u].append([v, w])
        self.graph[v].append([u, w])
    
    # Prim算法求解最小生成树
    def prim_mst(self):
        key = [float('inf')] * self.V  # 存储顶点的权值
        parent = [-1] * self.V  # 存储顶点的父节点
        in_mst = [False] * self.V  # 存储顶点是否在最小生成树中
        
        # 从第一个顶点开始
        key[0] = 0
        parent[0] = -1
        
        # 需要找到v-1条边
        for i in range(self.V - 1):
            # 找到距离生成树最近的顶点
            min_key = float('inf')
            for v in range(self.V):
                if in_mst[v] is False and key[v] < min_key:
                    min_key = key[v]
                    u = v
            
            in_mst[u] = True
            
            # 更新顶点的权值和父节点
            for v, w in self.graph[u]:
                if in_mst[v] is False and w < key[v]:
                    key[v] = w
                    parent[v] = u
        
        # 输出结果
        print("最小生成树为:")
        for i in range(1, self.V):
            print(f"{parent[i]} - {i} : {key[i]}")

下面是一个使用Prim算法求解最小生成树的示例:

g = Graph(5)
g.add_edge(0, 1, 2)
g.add_edge(0, 3, 6)
g.add_edge(1, 2, 3)
g.add_edge(1, 3, 8)
g.add_edge(1, 4, 5)
g.add_edge(2, 4, 7)
g.add_edge(3, 4, 9)

g.prim_mst()

输出结果为:

最小生成树为:
0 - 1 : 2
1 - 2 : 3
0 - 3 : 6
1 - 4 : 5

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Kruskal算法是一种用于求解最小生成树算法,它是基于贪心策略的。下面是一个用Python实现Kruskal算法的示例代码: ```python # 定义边的数据结构 class Edge: def __init__(self, src, dest, weight): self.src = src self.dest = dest self.weight = weight # 定义并查集数据结构 class UnionFind: def __init__(self, vertices): self.parent = {} self.rank = {} for v in vertices: self.parent[v] = v self.rank[v] = 0 def find(self, v): if self.parent[v] != v: self.parent[v] = self.find(self.parent[v]) return self.parent[v] def union(self, v1, v2): root1 = self.find(v1) root2 = self.find(v2) if self.rank[root1] < self.rank[root2]: self.parent[root1] = root2 elif self.rank[root1] > self.rank[root2]: self.parent[root2] = root1 else: self.parent[root2] = root1 self.rank[root1] += 1 # Kruskal算法实现 def kruskal(vertices, edges): mst = [] # 按照权重对边进行排序 edges.sort(key=lambda x: x.weight) uf = UnionFind(vertices) for edge in edges: src_root = uf.find(edge.src) dest_root = uf.find(edge.dest) if src_root != dest_root: mst.append(edge) uf.union(src_root, dest_root) return mst ``` 这段代码中,我们首先定义了边的数据结构`Edge`,包括边的起点、终点和权重。然后定义了并查集数据结构`UnionFind`,用于判断两个顶点是否在同一个集合中。最后实现了Kruskal算法`kruskal`,通过对边按权重排序,并使用并查集来判断是否形成环路,从而构建最小生成树。 你可以根据自己的需求调用`kruskal`函数,并传入顶点列表和边列表来求解最小生成树

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值