连通性问题改进算法

在上一篇“连通性问题”中已经对这个问题进行来介绍,在这一篇中给出针对以上问题的改进,在代码中已经对原理进行来注释。

加权快速合并算法

 1 /**
 2   * @file weightedquickunion.c
 3   * @brief 加权快速合并算法
 4   *        在合并操作中,不是任意把第二棵树连接到第一棵树上,而是记录每棵树中的节点数,
 5   *        总是把较小的树连接到较大的树上。这个程序是对快速合并算法的改进,用另一个数组
 6   *        sz记录每个id[i]==i的对象所在树中的节点数,使得合并操作能够将较小的树连接到
 7   *        较大的树上,以防止树中长路经的增长。
 8   * @date  2015-01-15
 9   */
10 #include <stdio.h>
11 #define N 1000
12 
13 int main(void)
14 {
15     int i, j, p, q;
16     int id[N], sz[N];
17     //初始化数组元素的初始值
18     for (i = 0; i < N; i++)
19     {
20         id[i] = i;
21         sz[i] = 1;
22     }
23     //循环读入整数对
24     while (scanf("%d-%d", &p, &q) == 2)
25     {
26         //查找p的根节点
27         for (i = p; i != id[i]; i = id[i]);
28         //查找q的根节点
29         for (j = q; j != id[j]; j = id[j]);
30         //如果p和q指向同一个根节点,则从标准输入读取下一对整数对
31         if (i == j) continue;
32         //否则,将p和q各自所在的树合并成一棵树
33         if (sz[i] < sz[j])
34         {//q所在的树较大
35             id[i] = j;     //将p所在的树连接到q所在树的根节点
36             sz[j] += sz[i];//q所在树的根节点存储的节点数在原基础上增加p所在树的节点数
37         }
38         else
39         {//p所在的树较大
40             id[j] = i;     //将q所在的树连接到p所在树的根节点
41             sz[i] += sz[j];//p所在树的根节点存储的节点数在原基础上增加q所在树的节点数
42         }
43         printf("New Pair: %d-%d\n", p, q);
44     }
45 
46     return 0;
47 }

 

路径压缩算法

 1 /**
 2   * @file pathcompression.c
 3   * @brief 带路径压缩的加权快速合并算法
 4   *        在合并操作中,不是任意把第二棵树连接到第一棵树上,而是记录每棵树中的节点数,
 5   *        总是把较小的树连接到较大的树上。这个程序是对快速合并算法的改进,用另一个数组
 6   *        sz记录每个id[i]==i的对象所在树中的节点数,使得合并操作能够将较小的树连接到
 7   *        较大的树上,以防止树中长路经的增长。
 8   * @brief 路径压缩:在合并操作过程中,添加经过每条路径的另一个指针,使沿路遇见的每个定
 9   *        点对应的id元素指向树的根节点。因为对于较短的路径,路径压缩没有多大作用,因此
10   *        在执行合并时,我们只对较大的树执行路径压缩,使经过的每个节点直接指向新的根节点。
11   * @brief 等分路径压缩:它通过使每条链接跳跃到树中向上节点的再向上一个节点来实现压缩。
12   * @date  2015-01-15
13   */
14 #include <stdio.h>
15 #define N 1000
16 #if 0
17 #define PATH_COMPRESSION  //路径压缩
18 #else
19 #define EQUAL_PATHCOMPRESSION  //等分路径压缩
20 #endif // 0
21 
22 int main(void)
23 {
24     int i, j, p, q, index;
25     int id[N], sz[N];
26     //初始化数组元素的初始值
27     for (i = 0; i < N; i++)
28     {
29         id[i] = i;
30         sz[i] = 1;
31     }
32     //循环读入整数对
33     while (scanf("%d-%d", &p, &q) == 2)
34     {
35     #ifdef EQUAL_PATHCOMPRESSION
36         //查找p的根节点
37         for (i = p; i != id[i]; i = id[i])
38             id[i] = id[id[i]];
39         //查找q的根节点
40         for (j = q; j != id[j]; j = id[j]);
41             id[j] = id[id[j]];
42     #else
43         //查找p的根节点
44         for (i = p; i != id[i]; i = id[i]);
45         //查找q的根节点
46         for (j = q; j != id[j]; j = id[j]);
47     #endif // EQUAL_PATHCOMPRESSION
48 
49         //如果p和q指向同一个根节点,则从标准输入读取下一对整数对
50         if (i == j) continue;
51         //否则,将p和q各自所在的树合并成一棵树
52         if (sz[i] < sz[j])
53         {//q所在的树较大
54             id[i] = j;     //将p所在的树连接到q所在树的根节点
55             sz[j] += sz[i];//q所在树的根节点存储的节点数在原基础上增加p所在树的节点数
56         #ifdef PATH_COMPRESSION
57             //对较大的树进行路径压缩
58             for (i = q; i != id[i];)
59             {
60                 index = i;     //存储当前节点号
61                 i = id[i];     //存储当前节点的父节点号
62                 id[index] = j; //当前节点指向新树的根节点
63             }
64         #endif // PATH_COMPRESSION
65         }
66         else
67         {//p所在的树较大
68             id[j] = i;     //将q所在的树连接到p所在树的根节点
69             sz[i] += sz[j];//p所在树的根节点存储的节点数在原基础上增加q所在树的节点数
70         #ifdef PATH_COMPRESSION
71             //对较大的树进行路径压缩
72             for (j= p; j != id[j];)
73             {
74                 index = j;     //存储当前节点号
75                 j = id[j];     //存储当前节点的父节点号
76                 id[index] = i; //当前节点指向新树的根节点
77             }
78         #endif // PATH_COMPRESSION
79         }
80         printf("New Pair: %d-%d\n", p, q);
81     }
82 
83     return 0;
84 }

 

posted @ 2015-01-15 21:18  XiaoManon  阅读(256)  评论(0编辑  收藏  举报