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

你可能感兴趣的:(Python经典算法,python,算法,开发语言)