python数据结构(最小生成树)

目录

最小生成树

克鲁斯卡尔算法

普里姆算法


最小生成树

对于有n个节点的无向连通图,无论其生成树的形态如何,所有的生成树必然没有回路,而且都有且仅有n-1条边。当无向连通图是一个带权图,其所有生成树中必有一颗边的权值总和最小的生成树,称为最小生成树。

最小生成树有两个算法:

克鲁斯卡尔(Kruskal)算法

普里姆(Prim)算法

克鲁斯卡尔算法

所有权值从小到大排序,顶点集合的有哪些,然后根据权值的小的优先进行排序,不进行回路

最后实例:

#coding=utf-8
class Graph(object):
    def init(self, maps):
        self.maps = maps
        self.nodenum = self.get_nodenum()   #节点
        self.edgenum = self.get_edgenum()   #边数
    def get_nodenum(self):
        return len(self.maps)
    def get_edgenum(self):
        count = 0
        for i in range(self.nodenum):
            for j in range(i):
                if self.maps[i][j] > 0 and self.maps[i][j] < 9999:
                    count += 1
        return count
    def kruskal(self):
        res = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
            return res
        edge_list = []
        for i in range(self.nodenum):
            for j in range(i,self.nodenum):
                if self.maps[i][j] < 9999:
                    edge_list.append([i, j, self.maps[i][j]]) #按[begin, end, weight]形式加入
        edge_list.sort(key=lambda a:a[2])    #已经排好序的边集合
        group = [[i] for i in range(self.nodenum)]
        for edge in edge_list:
            for i in range(len(group)):
                if edge[0] in group[i]:
                    m = i
                if edge[1] in group[i]:
                    n = i
            if m != n:
                res.append(edge)
                group[m] = group[m] + group[n]
                group[n] = []
        return res
max_value = 9999
row0 = [0,7,max_value,max_value,max_value,5]
row1 = [7,0,9,max_value,3,max_value]
row2 = [max_value,9,0,6,max_value,max_value]
row3 = [max_value,max_value,6,0,8,10]
row4 = [max_value,3,max_value,8,0,4]
row5 = [5,max_value,max_value,10,4,0]
maps = [row0, row1, row2,row3, row4, row5]
graph = Graph(maps)
print('邻接矩阵为\n%s'%graph.maps)
print('节点数据为%d,边数为%d\n'%(graph.nodenum, graph.edgenum))
print('------最小生成树kruskal算法------')
print(graph.kruskal())

程序运行示意图

普里姆算法

找一个顶点,然后找与此结点相连中间权值最小的结点选择,以此类推。如果到了没有结点可以访问的,或者是都是访问过的,则回到上一个或者是上几个,在已经访问了的节点中间还有没访问的结点,在这些没访问的几点中间找到权值相对于没访问的较小的权值进行访问。

最后实例:

#coding=utf-8
class Graph(object):
    def init(self, maps):
        self.maps = maps
        self.nodenum = self.get_nodenum()
        self.edgenum = self.get_edgenum()
    def get_nodenum(self):
        return len(self.maps)
    def get_edgenum(self):
        count = 0
        for i in range(self.nodenum):
            for j in range(i):
                if self.maps[i][j] > 0 and self.maps[i][j] < 9999:
                    count += 1
        return count
    def prim(self):
        res = []
        if self.nodenum <= 0 or self.edgenum < self.nodenum-1:
            return res
        res = []
        seleted_node = [0]
        candidate_node = [i for i in range(1, self.nodenum)]
        while len(candidate_node) > 0:
            begin, end, minweight = 0, 0, 9999
            for i in seleted_node:
                for j in candidate_node:
                    if self.maps[i][j] < minweight:
                        minweight = self.maps[i][j]
                        begin = i
                        end = j
            res.append([begin, end, minweight])
            seleted_node.append(end)
            candidate_node.remove(end)
        return res
max_value = 9999
row0 = [0,7,max_value,max_value,max_value,5]
row1 = [7,0,9,max_value,3,max_value]
row2 = [max_value,9,0,6,max_value,max_value]
row3 = [max_value,max_value,6,0,8,10]
row4 = [max_value,3,max_value,8,0,4]
row5 = [5,max_value,max_value,10,4,0]
maps = [row0, row1, row2,row3, row4, row5]
graph = Graph(maps)
print('邻接矩阵为\n%s'%graph.maps)
print('节点数据为%d,边数为%d\n'%(graph.nodenum, graph.edgenum))
print('------最小生成树prim算法')
print(graph.prim())

数据结构课程设计中的最小生成树是一个经典的算法问题,通常要求学生掌握图论的基本概念以及几种构建最小生成树算法最小生成树指的是在一个加权连通图中找到一个边的子集,这个子集构成一个树形结构,且所有顶点都在树中,并且这些边的权值之和尽可能小。 在进行最小生成树的课程设计时,可以包含以下几个关键部分: 1. 图论基础:首先需要了解图的基本概念,包括顶点(节点)、边、权值、连通性、无向图和有向图等。 2. 最小生成树的定义和性质:理解最小生成树的定义,以及它在加权连通图中所具有的重要性质,比如总是包含n-1条边(n为图中顶点的数量)。 3. 最小生成树算法:课程设计中通常会要求学生实现两种著名的最小生成树算法——Prim算法和Kruskal算法。 - Prim算法从一个顶点开始,每次从未处理的顶点中选取与已处理顶点集合距离最近的顶点加入到已处理集合中,直到所有顶点都被处理。 - Kruskal算法则是将所有边按权重从小到大排序,然后按照排序结果逐一加入生成树中,同时保证不形成环。 4. 算法实现:学生需要使用一种编程语言(如C/C++、Java或Python)来实现上述算法,并能够处理各种不同大小和结构的图。 5. 实验报告:编写实验报告,详细说明实验目的、算法原理、实验步骤、实验结果和分析。 6. 测试案例:设计多种测试案例来验证所实现算法的正确性和效率,包括小型图和大型图的测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值