zoukankan      html  css  js  c++  java
  • 连通性问题改进算法

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

    加权快速合并算法

     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
    ", 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
    ", p, q);
    81     }
    82 
    83     return 0;
    84 }
  • 相关阅读:
    Linux内存初始化
    linux PCI设备初始化过程
    Linux网络地址转换分析
    Linux内核中流量控制
    IPSEC实现
    ip_conntrack 实现
    module_init宏解析
    IP隧道基础研究
    IPV6介绍
    Golang的接口
  • 原文地址:https://www.cnblogs.com/xiaomanon/p/4227282.html
Copyright © 2011-2022 走看看