python实现Kruskal算法求解加权图中最小生成树问题

320 篇文章 88 订阅
151 篇文章 4 订阅

    继上一篇文章的Prim算法,今天学习使用的是Kruskal算法,Prim和Kruskal算法作用是相同的,都是为了求解加权图问题中的最小生成树,至于Kruskal算法的原理也是很好理解的,这里不多累赘简单概要一下Kruskal算法的的核心思想:

    首先设置一个空的集合A,依次从原始图中寻找权重最小的边加入到A中,一个前提和原则是:不能形成回路,n个顶点,当A中存在n-1条边的时候算法终止

    核心思想就是这么简洁,但是算法这东西,往往就是越简单越是容易被接受和使用,我本人对于Kruskal算法和Prim算法在本科的时候考试做题编程都是使用Kruskal算法居多,可能就是感觉这个做起来更方便了一点,简单实现了一下如下:

#!usr/bin/env python
#encoding:utf-8

'''
__Author__:沂水寒城
功能:使用Kruskal算法求加权连通图的最小生成树
'''


import random
import time
import numpy


def random_matrix_genetor(vex_num=10):
    '''
    随机图顶点矩阵生成器
    输入:顶点个数,即矩阵维数
    '''
    data_matrix=[]
    for i in range(vex_num):
        one_list=[]
        for j in range(vex_num):
            one_list.append(random.randint(1, 100))
        data_matrix.append(one_list)
    return data_matrix


def Kruskal(data_matrix):
    '''
    Kruskal 算法
    输入:图矩阵
    输出:加权最小生成树总权重
    '''
    vex_num=len(data_matrix)
    kruskal=[]
    weights=[]
    start_set=[]
    end_set=[]
    for i in range(vex_num):
        kruskal.append([i])
        for j in range(i+1,vex_num):
            if data_matrix[i][j]!='N':
                start_set.append(i)
                end_set.append(j)
                weights.append(data_matrix[i][j])
    distance=0
    for i in range(vex_num):
        tmp=numpy.argsort(weights)[0]
        for j in range(vex_num):
            if start_set[tmp] in kruskal[j]:
                m=j
            if end_set[tmp] in kruskal[j]:
                n=j
        if m!=n:
            kruskal[m]=kruskal[m]+kruskal[n]
            kruskal[n]=[]
            distance+=weights[tmp]
        weights.pop(tmp)
        start_set.pop(tmp)
        end_set.pop(tmp)
    print '加权最小生成树总权重为:', distance
    return distance

    

def main_test_func(vex_num=10):
    '''
    主测试函数
    '''
    start_time=time.time()
    data_matrix=random_matrix_genetor(vex_num)
    distance=Kruskal(data_matrix)
    end_time=time.time()
    return end_time-start_time


 
if __name__=='__main__':
    data_matrix=[[0,3,1,'N'],[3,0,2,4],[1,2,0,5],['N',4,5,0]]
    print data_matrix
    Kruskal(data_matrix)   
    
    time_list=[]
    print '----------------------------10顶点测试-------------------------------------'
    time10=main_test_func(10)
    time_list.append(time10)

    print '----------------------------50顶点测试-------------------------------------'
    time50=main_test_func(50)
    time_list.append(time50)

    print '----------------------------100顶点测试-------------------------------------'
    time100=main_test_func(100)
    time_list.append(time100)

    print '----------------------------1000顶点测试-------------------------------------'
    time1000=main_test_func(1000)
    time_list.append(time1000)

    print '---------------------------------时间消耗对比--------------------------------'
    for one_time in time_list:
        print one_time

结果如下:

[[0, 3, 1, 'N'], [3, 0, 2, 4], [1, 2, 0, 5], ['N', 4, 5, 0]]
加权最小生成树总权重为: 7
----------------------------10顶点测试-------------------------------------
加权最小生成树总权重为: 111
----------------------------50顶点测试-------------------------------------
加权最小生成树总权重为: 103
----------------------------100顶点测试-------------------------------------
加权最小生成树总权重为: 116
----------------------------1000顶点测试-------------------------------------
加权最小生成树总权重为: 834
---------------------------------时间消耗对比--------------------------------
0.0
0.010999917984
0.0670001506805
57.513999939
[Finished in 58.1s]

    时间上的话可以看出来的确是跟Prim算法相差了一大截,尤其是当数据规模增大的时候,这个变得极其明显,我个人只是在做习题相关的时候更偏重于使用Kruskal算法的思想来求解得到加权图中的最小生成树,Prim算法在应对大数据规模的图矩阵的时候有着无可比拟的优势,这一点自然就被用于大规模的数据中了,当然,二者都是很优秀的算法,各有千秋

   好了,简单的学习了一下,学习中也查阅了相关的网上资料,关于Kruskal算法就到这里了,如有兴趣欢迎讨论!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Together_CZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值