快速查找 快速合并 加权快速合并 路径等分加权快速合并 算法

快速查找

 1 #include <stdio.h>
 2 
 3 #define N 10000
 4 
 5 int main(void)
 6 {
 7     int i,p,q,t,id[N];
 8     //p,q 连接对数
 9     //id被查找数组
10     for(i=0; i<N; i++)
11         id[i]=i;
12     //初始化数组
13     while(scanf("%d %d
", &p, &q)==2)
14     {
15         //输入连接对数
16         if(id[p]==id[q])continue;
17         //如果id[p]=id[q] p,q连通
18         for(t=id[p],i=0; i<N; i++)
19             if(id[i]==t)
20                id[i]=id[q];
21         /*遍历数组id[0<=i<N],从0到p,
22           将id[p]的值改为id[q],p-q连通*/
23         printf(" %d %d
", p, q);
24         //打印首次连通的值
25     }
26     return 0;
27 }
28 
29 /*求解N个对象的连通性问题,如果执行M次合并操作,
30   那么快速查找算法至少执行MN条指令            */ 

快速合并

 1 #include <stdio.h>
 2 
 3 #define N 10000
 4 
 5 int main(void)
 6 {
 7     int i,p,q,j,id[N];
 8     //p,q 连接对数
 9     //id被查找数组
10     for(i=0; i<N; i++)
11         id[i]=i;
12     //初始化数组
13     while(scanf("%d %d
", &p, &q)==2)
14     {
15         //输入连接对数
16         for(i=p; i!=id[i]; i=id[i]);
17         for(j=q; j!=id[j]; j=id[j]);
18         //将i,j指向p,q的树根
19         if(i==j)continue;
20         //如果pq已连通就跳出本次循环
21         id[i]=j;
22         //将pq连通
23         printf(" %d %d
", p, q);
24         //打印首次连通的值
25     }
26     return 0;
27 }
28 /*对于M>N,快速合并算法求解N个对象,M个对的连通问题
29   需要执行MN/2条指令,最坏情形每次执行(N-1)/2    */

加权快速合并算法

 1 #include <stdio.h>
 2 
 3 #define N 10000
 4 
 5 int main(void)
 6 {
 7     int i,p,q,j,id[N],sz[N];
 8     /*p,q 连接对数,id被查找数组
 9       sz数组记录每个id[0<=i<N]==0<=i<N的对象
10       所在树中的节点数,使得合并操作能够把较小的
11       树连接到较大的树上,防止树中路径的增长*/
12     for(i=0; i<N; i++)
13     {
14         id[i]=i;
15         sz[i]=1;
16     }
17     //初始化数组
18     while(scanf("%d %d
", &p, &q)==2)
19     {
20         //输入连接对数
21         for(i=p; i!=id[i]; i=id[i]);
22         for(j=q; j!=id[j]; j=id[j]);
23         //将i,j指向p,q的树根
24         if(i==j)continue;
25         //如果pq已连通就跳出本次循环
26         if(sz[i]<sz[j])
27         {
28             id[i]=j;
29             sz[j]+=sz[i];
30         }
31         else
32         {
33             id[j]=i;
34             sz[i]+=sz[j];
35         }
36         //将较小的树连接到较大的树
37         //将pq连通
38         printf(" %d %d
", p, q);
39         //打印首次连通的值
40     }
41     return 0;
42 }
43 /*对于N个对象,加权快速合并算法判定
44   其中的两个对象是否连通的,至多需要
45   遍历2lgN个指针                    */

等分路径压缩

 1 #include <stdio.h>
 2 
 3 #define N 10000
 4 
 5 int main(void)
 6 {
 7     int i,p,q,j,id[N],sz[N];
 8     /*p,q 连接对数,id被查找数组
 9       sz数组记录每个id[0<=i<N]==0<=i<N的对象
10       所在树中的节点数,使得合并操作能够把较小的
11       树连接到较大的树上,防止树中路径的增长*/
12     for(i=0; i<N; i++)
13     {
14         id[i]=i;
15         sz[i]=1;
16     }
17     //初始化数组
18     while(scanf("%d %d
", &p, &q)==2)
19     {
20         //输入连接对数
21         /***************************/
22         for(i=p; i!=id[i]; i=id[i])
23             id[i]=id[id[i]];
24         for(j=q; j!=id[j]; j=id[j])
25             id[j]=id[id[j]];
26        /***************************/
27         if(i==j)continue;
28         //如果pq已连通就跳出本次循环
29         if(sz[i]<sz[j])
30         {
31             id[i]=j;
32             sz[j]+=sz[i];
33         }
34         else
35         {
36             id[j]=i;
37             sz[i]+=sz[j];
38         }
39         //将较小的树连接到较大的树
40         //将pq连通
41         printf(" %d %d
", p, q);
42         //打印首次连通的值
43     }
44     return 0;
45 }

代码块的注释:

则不改变。

如果深度为3,则

->

深度为4

->

深度为5

深度为6

这样每个节点的深度小了。搜索根节点的复杂度变小

原文地址:https://www.cnblogs.com/WALLACE-S-BOOK/p/8649010.html