并集-查找算法

I.快速查找算法:
========================quick_find.c=================================
#include<stdio.h>
#define N 10
int main(){
 int id[N];
 int i, p, q, t, count, sum = 0;
 for(i = 0; i < N; i++) id[i] = i;
 while (scanf("%d %d", &p, &q) == 2){
  count = 0;
  if(id[p] == id[q]) continue;
  //下面的这个for循环很有意思,它具有记忆功能:记忆之前连通的数!
  for(t = id[p], i = 0; i < N; i++)
   if(id[i] == t){
     id[i] = id[q];  
    count++;
    sum ++;
   }
  printf("count = %d, sum = %d/n", count, sum);
  for(i = 0; i < N; i++) printf("%d ", id[i]);
  printf("/n");
 }
 
}

=====编译运行=====
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ gcc quick_find.c
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ ./a.out
0 2
count = 1, sum = 1
2 1 2 3 4 5 6 7 8 9
1 4
count = 1, sum = 2
2 4 2 3 4 5 6 7 8 9
2 5
count = 2, sum = 4
5 4 5 3 4 5 6 7 8 9
3 6
count = 1, sum = 5
5 4 5 6 4 5 6 7 8 9
0 4
count = 3, sum = 8
4 4 4 6 4 4 6 7 8 9
6 0
count = 2, sum = 10
4 4 4 4 4 4 4 7 8 9
1 3

 

II.快速并集算法:
===================quick_union.c=======================================
#include<stdio.h>
#define N 10

/*
 *这个一个连通性问题的快速union的解决方案。
 */
int main(){
 int id[N];
 int i, j, p, q;
 int count_i, count_j, sum = 0;
 for(i = 0; i < N; i++) id[i] = i;
 while(scanf("%d %d", &p, &q) == 2){
  //下面是很有意思的两个for循环!如果输入的位置的值被改动过,此处的i可能出现多个值,例如,1 1 9 4 9 6 9 9 0 0 输入 5 5,首先i=5发现5号位置被改动过->i=9发现9号位置也被改动->i=0发现0号位置也被改动,继续给i赋值->i=1,好了发现1号位置没有被改动,OK 最终i=1;

  //这个for循环的作用总结为:追踪上一级的位置有没有被改动!直到找到一个没有被改动的位置的值附给变量。
  count_i = count_j = 0;
  for(i = p; i != id[i]; i = id[i]) {count_i++; sum++;}   
  for(j = q; j != id[j]; j = id[j]) {count_j++; sum++;}
  if(i == j) continue;
  id[i] = j;
  count_i++;
  sum++;
  printf("访问数组id的次数:%d/n", count_i + count_j);
  printf("访问数组id的总数:%d/n", sum);
  for(i = 0; i < N; i++) printf("%d ", id[i]);
  printf("/n/n"); 
 }
}

=======编译运行===========
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ gcc quick_union.c
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ ./a.out
0 2
访问数组id的次数:1
访问数组id的总数:1
2 1 2 3 4 5 6 7 8 9

1 4
访问数组id的次数:1
访问数组id的总数:2
2 4 2 3 4 5 6 7 8 9

2 5
访问数组id的次数:1
访问数组id的总数:3
2 4 5 3 4 5 6 7 8 9

3 6
访问数组id的次数:1
访问数组id的总数:4
2 4 5 6 4 5 6 7 8 9

0 4
访问数组id的次数:3
访问数组id的总数:7
2 4 5 6 4 4 6 7 8 9

6 0
访问数组id的次数:4
访问数组id的总数:11
2 4 5 6 4 4 4 7 8 9

1 3

 

III.加权快速并集算法:
=========================weighted_quick_union.c=========================================
#include<stdio.h>
#define N 10

/*
 *这个一个连通性问题的快速加权union的解决方案。
 */
int main(){
 int id[N], sz[N];
 int i, j, p, q;
 int count_i, count_j, sum = 0;
 for(i = 0; i < N; i++){
   id[i] = i;
  sz[i] = 1;
 }
 while(scanf("%d %d", &p, &q) == 2){
  count_i = count_j  = 0;
  for(i = p; i != id[i]; i = id[i]){count_i++; sum++;}  
  for(j = q; j != id[j]; j = id[j]){count_j++; sum++;}
  if(i == j) continue;
  if(sz[i] < sz[j]){
   id[i] = j;
   count_i++;
   sum++;
   sz[j] += sz[i];
  } else {
   id[j] = i;
   count_j++;
   sum++;
   sz[i] += sz[j];
  }
  printf("访问数组id的次数:%d/n", count_i+count_j);
  printf("访问数组id的总次数:%d/n", sum);
  for(i = 0; i < N; i++) printf("%d ", id[i]);
  printf("/n/n"); 
 }
}
=========编译运行============
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ gcc weighted_quick_union.c
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ ./a.out
0 2
访问数组id的次数:1
访问数组id的总次数:1
0 1 0 3 4 5 6 7 8 9

1 4
访问数组id的次数:1
访问数组id的总次数:2
0 1 0 3 1 5 6 7 8 9

2 5
访问数组id的次数:2
访问数组id的总次数:4
0 1 0 3 1 0 6 7 8 9

3 6
访问数组id的次数:1
访问数组id的总次数:5
0 1 0 3 1 0 3 7 8 9

0 4
访问数组id的次数:2
访问数组id的总次数:7
0 0 0 3 1 0 3 7 8 9

6 0
访问数组id的次数:2
访问数组id的总次数:9
0 0 0 0 1 0 3 7 8 9

1 3


IV.分路径压缩加权快速并集算法:
====================weighted_quick_union_pc_hal.c================================
#include<stdio.h>
#define N 10

/*
 *这个一个连通性问题的分路径压缩快速加权union的解决方案。
 */
int main(){
 int id[N], sz[N];
 int i, j, p, q;
 int count_i, count_j, sum = 0;
 for(i = 0; i < N; i++){
   id[i] = i;
  sz[i] = 1;
 }
 while(scanf("%d %d", &p, &q) == 2){
  count_i = count_j  = 0;
  for(i = p; i != id[i]; i = id[i]){
   id[i] = id[id[i]];
   count_i += 4;
   sum += 4;
  }  
  for(j = q; j != id[j]; j = id[j]){
   id[j] = id[id[j]];
   count_j += 4;
   sum += 4;
  }
  if(i == j) continue;
  if(sz[i] < sz[j]){
   id[i] = j;
   count_i++;
   sum++;
   sz[j] += sz[i];
  } else {
   id[j] = i;
   count_j++;
   sum++;
   sz[i] += sz[j];
  }
  printf("访问数组id的次数:%d/n", count_i+count_j);
  printf("访问数组id的总次数:%d/n", sum);
  for(i = 0; i < N; i++) printf("%d ", id[i]);
  printf("/n/n"); 
 }
}

==============编译运行=====================
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ gcc weighted_quick_union_pc_hal.c
explore@ubuntu:~/Documents/datastruct/Algorithms in C/第一章  导论$ ./a.out
0 2
访问数组id的次数:1
访问数组id的总次数:1
0 1 0 3 4 5 6 7 8 9

1 4
访问数组id的次数:1
访问数组id的总次数:2
0 1 0 3 1 5 6 7 8 9

2 5
访问数组id的次数:5
访问数组id的总次数:7
0 1 0 3 1 0 6 7 8 9

3 6
访问数组id的次数:1
访问数组id的总次数:8
0 1 0 3 1 0 3 7 8 9

0 4
访问数组id的次数:5
访问数组id的总次数:13
0 0 0 3 1 0 3 7 8 9

6 0
访问数组id的次数:5
访问数组id的总次数:18
0 0 0 0 1 0 3 7 8 9

1 3

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值