快速查找
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\n", &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\n", 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\n", &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\n", 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\n", &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\n", 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\n", &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\n", p, q);
42 //打印首次连通的值
43 }
44 return 0;
45 }
代码块的注释:
或
则不改变。
如果深度为3,则
->
深度为4
->
深度为5
深度为6
这样每个节点的深度小了。搜索根节点的复杂度变小