zoukankan      html  css  js  c++  java
  • 并查集效率测试

    pre
    全文基础设定
    -----------------------------
    n 集合总数(即并查集个体数)
    m 总共操作数
    f find操作数
    Ackerman(k,n) = {n+1/k==0 | Ackerman.iter(n+1,k=k-1)(k-1,n)} / 具体定义可以看wiki
    alpha(n) = min{k:Ackerman(k,1)>=n}

    引自《算法导论》

    并查集(disjoint set)有两种优化: 按秩合并(union by rank,UR) 和 路径压缩(path compression,PC)

    其中,
    仅用按秩合并的时间复杂度$ ext{O} ( m log n)$
    仅用路径压缩的时间复杂度$Theta ( n + f cdot ( 1 + log_{2 + f / n} n))$
    两个都用的时间复杂度$ ext{O} ( m alpha ( n))$

    测试程序

    并查集程序

    #define sizex 100000000
    int f[sizex],rk[sizex];
    struct ds{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1;
    	}
    	void find(int t){
    		return ~f[t]?t:find(f[t]);
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		f[b]=a;
    	}
    } djs;
    struct dsU{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1,rk[i]=1;
    	}
    	void find(int t){
    		return ~f[t]?t:find(f[t]);
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		if(rk[a]>=rk[b]){
    			f[b]=a;
    			rk[a]+=rk[b];
    		}else{
    			f[a]=b;
    			rk[b]+=rk[a];
    		}
    	}
    } djsU;
    struct dsP{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1;
    	}
    	void find(int t){
    		return ~f[t]?t:f[t]=find(f[t]);
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		f[b]=a;
    	}
    } djsP;
    struct dsUP{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1,rk[i]=1;
    	}
    	void find(int t){
    		return ~f[t]?t:f[t]=find(f[t]);
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		if(rk[a]>=rk[b]){
    			f[b]=a;
    			rk[a]+=rk[b];
    		}else{
    			f[a]=b;
    			rk[b]+=rk[a];
    		}
    	}
    } djsUP;

    测试程序

    #define sizex 100000000
    int f[sizex],rk[sizex];
    struct ds{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1;
    	}
    	int find(int t){
    		return ~f[t]?find(f[t]):t;
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		f[b]=a;
    	}
    } djs;
    struct dsU{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1,rk[i]=1;
    	}
    	int find(int t){
    		return ~f[t]?find(f[t]):t;
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		if(rk[a]>=rk[b]){
    			f[b]=a;
    			rk[a]+=rk[b];
    		}else{
    			f[a]=b;
    			rk[b]+=rk[a];
    		}
    	}
    } djsU;
    struct dsP{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1;
    	}
    	int find(int t){
    		return ~f[t]?f[t]=find(f[t]):t;
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		f[b]=a;
    	}
    } djsP;
    struct dsUP{
    	inline void init(int size){
    		for(int i=0;i<size;++i) f[i]=-1,rk[i]=1;
    	}
    	int find(int t){
    		return ~f[t]?f[t]=find(f[t]):t;
    	}
    	inline void join(int a,int b){
    		a=find(a),b=find(b);
    		if(a==b) return;
    		if(rk[a]>=rk[b]){
    			f[b]=a;
    			rk[a]+=rk[b];
    		}else{
    			f[a]=b;
    			rk[b]+=rk[a];
    		}
    	}
    } djsUP;
    #include <cstdio>
    #include <random>
    #include <malloc.h>
    #include <sys/time.h>
    using namespace std;
    struct cmd{
    	bool type;
    	int a,b;
    }temp;
    cmd* data;
    long long mytic(){
    	long long result = 0.0;
    	struct timeval tv;
    	gettimeofday( &tv, NULL );
    	result = ((long long)tv.tv_sec)*1000000 + (long long)tv.tv_usec;
    	return result;
    }
    #define dic1() disA(generator)
    #define dic2() disB(generator)
    void genData(int a,int b,int c){
    	mt19937 generator;
    	uniform_int_distribution<int> disA(0,a-1);
    	uniform_int_distribution<int> disB(0,b+c-1);
    	int k=b+c,i=0,j;
    	for(;i<b;++i) data[i].type=0,data[i].a=dic1(),data[i].b=dic1();
    	for(;i<k;++i) data[i].type=1,data[i].a=dic1();
    	for(i=0;i<k;++i){
    		j=dic2();
    		if(i==j) continue;
    		temp=data[i];
    		data[i]=data[j];
    		data[j]=temp;
    	}
    }
    void testN(int a,int b,int c){
    	int k=b+c,i;
    	printf("none opt
    ");
    	long long start=mytic();
    	djs.init(a);
    	for(i=0;i<k;++i){
    		switch(data[i].type){
    			case 0:
    			djs.join(data[i].a,data[i].b);
    			case 1:
    			djs.find(data[i].a);
    		}
    	}
    	start=mytic()-start;
    	printf("Time usage: %lld us
    ",start);
    }
    void testU(int a,int b,int c){
    	int k=b+c,i;
    	printf("union by rank opt
    ");
    	long long start=mytic();
    	djsU.init(a);
    	for(i=0;i<k;++i){
    		switch(data[i].type){
    			case 0:
    			djsU.join(data[i].a,data[i].b);
    			case 1:
    			djsU.find(data[i].a);
    		}
    	}
    	start=mytic()-start;
    	printf("Time usage: %lld us
    ",start);
    }
    void testP(int a,int b,int c){
    	int k=b+c,i;
    	printf("path compression opt
    ");
    	long long start=mytic();
    	djsP.init(a);
    	for(i=0;i<k;++i){
    		switch(data[i].type){
    			case 0:
    			djsP.join(data[i].a,data[i].b);
    			case 1:
    			djsP.find(data[i].a);
    		}
    	}
    	start=mytic()-start;
    	printf("Time usage: %lld us
    ",start);
    }
    void testUP(int a,int b,int c){
    	int k=b+c,i;
    	printf("both opt
    ");
    	long long start=mytic();
    	djsUP.init(a);
    	for(i=0;i<k;++i){
    		switch(data[i].type){
    			case 0:
    			djsUP.join(data[i].a,data[i].b);
    			case 1:
    			djsUP.find(data[i].a);
    		}
    	}
    	start=mytic()-start;
    	printf("Time usage: %lld us
    ",start);
    }
    int main(){
    	int a,b,c,i,j,k,l,m,n,N,U,P,UP;
    	data=(cmd*)malloc(200000000*sizeof(cmd));
    	while(printf("0 to quit> "),scanf("%d",&a),a){
    		printf("N U P UP
    ");
    		scanf("%d%d%d%d",&N,&U,&P,&UP);
    		printf("set size: ");
    		scanf("%d",&a);
    		printf("op join num: ");
    		scanf("%d",&b);
    		printf("op find num: ");
    		scanf("%d",&c);
    		if(a>100000000||(b+c)>200000000) continue;
    		i=b+c;
    		printf("total %d ops
    ", b+c);
    		genData(a,b,c);
    		if(N) testN(a,b,c);
    		if(U) testU(a,b,c);
    		if(P) testP(a,b,c);
    		if(UP) testUP(a,b,c);
    	}
    	free(data);
    	return 0;
    }
    

    raw data

    set size: 500	join operations: 500	find operations: 500
    total 1000 ops
    none opt Time usage: 383 us
    Union by Rank opt Time usage: 44 us
    Path Compression opt Time usage: 48 us
    both opt(s) Time usage: 39 us
    set size: 10000	join operations: 7000	find operations: 10000
    total 17000 ops
    none opt Time usage: 1159 us
    Union by Rank opt Time usage: 246 us
    Path Compression opt Time usage: 274 us
    both opt(s) Time usage: 245 us
    set size: 100000	join operations: 70000	find operations: 100000
    total 170000 ops
    none opt Time usage: 134035 us
    Union by Rank opt Time usage: 3096 us
    Path Compression opt Time usage: 3291 us
    both opt(s) Time usage: 2967 us
    set size: 400000	join operations: 280000	find operations: 400000
    total 680000 ops
    none opt Time usage: 5293524 us
    Union by Rank opt Time usage: 14099 us
    Path Compression opt Time usage: 14466 us
    both opt(s) Time usage: 12509 us
    set size: 1000000	join operations: 700000	find operations: 1000000
    total 1700000 ops
    Union by Rank opt Time usage: 48863 us
    Path Compression opt Time usage: 40933 us
    both opt(s) Time usage: 41501 us
    set size: 10000000	join operations: 7000000	find operations: 10000000
    total 17000000 ops
    Union by Rank opt Time usage: 882355 us
    Path Compression opt Time usage: 1118981 us
    both opt(s) Time usage: 814115 us
    set size: 100000000	join operations: 70000000	find operations: 100000000
    total 170000000 ops
    Union by Rank opt Time usage: 13025344 us
    Path Compression opt Time usage: 19499277 us
    both opt(s) Time usage: 12493686 us
    (-O2)
    =================================================== set size: 100000000 join operations: 60000000 find operations: 120000000 total 180000000 ops Union by Rank opt Time usage: 10360505 us Path Compression opt Time usage: 11255217 us both opt(s) Time usage: 9452136 us
    (-O3) ===================================================== bug fixed: add `break' set size: 100000000 join operations: 60000000 find operations: 120000000 total 180000000 ops Union by Rank opt Time usage: 12039494 us Path Compression opt Time usage: 13178722 us both opt(s) Time usage: 13395750 us set size: 100000000 join operations: 50000000 find operations: 140000000 total 190000000 ops Union by Rank opt Time usage: 11454054 us Path Compression opt Time usage: 10056804 us both opt(s) Time usage: 11322394 us set size: 100000000 join operations: 100000000 find operations: 100000000 total 200000000 ops Union by Rank opt Time usage: 20773924 us Path Compression opt Time usage: 46671332 us both opt(s) Time usage: 19270817 us (-O3)
  • 相关阅读:
    30分钟掌握ES6/ES2015核心内容(下)
    30分钟掌握ES6/ES2015核心内容(上)
    域名、主机名与URL
    localstorage sessionstorage cookie的区别
    http中post 和 get 请求方法区别
    leetcode33. 搜索旋转排序数组
    leetcode 56. 合并区间
    MySQL EXPLAIN
    array 数组
    判断一个字符串的所有字符是否都在另一个字符串中
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4375123.html
Copyright © 2011-2022 走看看