Python数据结构与算法(十八、几种版本的并查集性能对比)

保证一周更两篇吧,以此来督促自己好好的学习!代码的很多地方我都给予了详细的解释,帮助理解。好了,干就完了~加油!
声明:本python数据结构与算法是imooc上liuyubobobo老师java数据结构的python改写,并添加了一些自己的理解和新的东西,liuyubobobo老师真的是一位很棒的老师!超级喜欢他~
如有错误,还请小伙伴们不吝指出,一起学习~
No fears, No distractions.

一、测试代码的实现

上一期我们实现了最基础的并查集及其若干改进版本,本期我们来对这几种并查集做一个性能比较。
废话不多说,直接上代码

# -*- coding: utf-8 -*-
# Author:           Annihilation7
# Date:             2019-01-13   4:15 pm
# Python version:   3.6 

import numpy as np
import time
import union_find1, union_find2, union_find3, union_find4, union_find5, union_find6


class test_uf:
    def __init__(self, length, op_nums):
        self.length = length 
        self.op_nums = op_nums

        self.uf1 = union_find1.Union_Find1(self.length)
        self.uf2 = union_find2.Union_Find2(self.length)
        self.uf3 = union_find3.Union_Find3(self.length)
        self.uf4 = union_find4.Union_Find4(self.length)
        self.uf5 = union_find5.Union_Find5(self.length)
        self.uf6 = union_find6.Union_Find6(self.length)
        self.uf = [self.uf1, self.uf2, self.uf3, self.uf4, self.uf5, self.uf6]
        self.name = [
            'union_find\t\t\t\t\t',
            'quick_union\t\t\t\t\t',
            '基于size改进的quick_union\t\t\t',
            '基于rank改进的quick_union\t\t\t',
            '基于路径压缩改进的rank_quick_union\t\t',
            '基于压缩到树高为1的路径压缩的rank_quick_union\t'

        ]

        tmp1 = [np.random.randint(self.length) for i in range(self.op_nums)]
        tmp2 = [np.random.randint(self.length) for i in range(self.op_nums)]
        tmp3 = [np.random.randint(self.length) for i in range(self.op_nums)]
        tmp4 = [np.random.randint(self.length) for i in range(self.op_nums)]
        self.op_indexes_1 = [tmp1, tmp2]
        self.op_indexes_2 = [tmp3, tmp4]

        
    def test(self):
        for uf, name in zip(self.uf, self.name):
            start_time = time.time()
            for i, j in zip(self.op_indexes_1[0], self.op_indexes_1[1]):
                uf.unionElements(i, j)   # self.op_nums次union操作
            for m, n in zip(self.op_indexes_2[0], self.op_indexes_2[1]):
                uf.isConnected(m, n)   # 紧接着self.op_nums次isConnected操作,不需要返回值
            end_time = time.time()
            print(name+'耗时:{}s'.format(end_time - start_time))
        

if __name__ == '__main__':
    print('并查集长度为100000,操作数为100000的条件下:')
    Test = test_uf(
        length=10000,
        op_nums=100000
    )
    Test.test()

    

二、 输出结果

union_find                                 	耗时:7.599979877471924s
quick_union                                	耗时:48.96020698547363s
基于size改进的quick_union                    	耗时:0.2335207462310791s
基于rank改进的quick_union                    	耗时:0.22702598571777344s
基于路径压缩改进的rank_quick_union     		耗时:0.22435784339904785s
基于压缩到树高为1的路径压缩的rank_quick_union   	耗时:0.27929210662841797s

三、结果分析

  1. 从输出结果可以看出,quick_union由于让树的高度一直在增加,所以一定在isConnected方法上消耗很多时间,还没有union_find快呢。后面的四种优化方法在性能上差不多,但是我的这里数据量比较小,如果数据量和操作数都在千万级别的话,uf5一定是最快的,也就是“基于路径压缩改进的rank_quick_union”。大家还能够发现一个很有意思的情况,就是最后一个方法并不是最快的,这取决于当时计算机的状态,因为里面有递归函数,大量的递归调用有时也会对性能产生一定的损失。所以“基于路径压缩改进的rank_quick_union”大家一定要掌握!!
  2. 下期我们回到二叉树,讲述最早诞生的平衡二叉树——AVL树。下期见~

若有还可以改进、优化的地方,还请小伙伴们批评指正!

你可能感兴趣的:(并查集,性能,数据结构,算法,python,python数据结构与算法,Python数据结构与算法)