Union-Find C语言实现

本文是基于《算法(第四版)》中的Union Find讲解,采用C语言实现了Quick Find和Quick Union。

1. 概述

  给定N个对象,dynamic connectivity主要研究以下两个问题:
1. 判断p和q是否相连。
2. 连接两个对象p和q。
  在建立模型时采用一维数组存放0~N-1个对象的信息,这样可以简化很多很UF无关的细节。

2. Quick Find

  假设把0~N-1个对象放在数组id[ ]中,每次读进来一对(p,q)时,如果相连的话就continue,如果不相连则通过把id[p]的内容改为id[q]的内容使它们连接起来。此时第1节中的两个问题等价于:
1. id[p] ?= id[q]
2. 把所有的id[p]都换成id[q]
  代码如下:

#include <stdio.h>
#include <malloc.h>

bool query(int* id, int p, int q)
{
    //判断id[p]和id[q]是否连通,是返回1,否返回0
    return *(id + p) == *(id + q);
}

void union_command(int *id, int N, int p, int q)
{
    int k;
    int idp = *(id + p);
    int idq = *(id + q);
    for (k = 0; k < N; k++)
    {
        if (*(id + k) == idp)
            *(id + k) = idq;
    }
}

int main()
{
    int N;
    int *id;
    int i, p, q;
    printf("Input node number:\n");
    scanf_s("%d", &N);
    id = (int*)malloc(N*sizeof(int));

    //初始化
    for (i = 0; i < N; i++)
        *(id + i) = i;

    //接受输入对,判断是否连通,若否创建连接
    while (scanf_s("%d %d", &p, &q) == 2)
    {
        if (!query(id, p, q))
        {
            //union_command(id, N, p, q);
            union_command(id, p, q);
        }       

        //将数组打印出来看一下
        for (i = 0; i < N; i++)
            printf("%d  ", *(id + i));
        printf("\n");
    }

    return 0;
}

  测试时可以采用书上的例子:
       这里写图片描述

3. Quick Union

  Quick Find的缺陷在于每次要把id[p]换成id[q]的时候都需要遍历数组。Quick Union相当于Quick Find的改进算法,目的在于减少遍历次数。具体做法就是把数组中的元素看作是树中的parent。这样第1节中的两个问题转化为:
1. 判断p和q是否具有同一个root。
2. union的时候把p的root改为q的root。
  代码中只需要改union_command函数:

void union_command(int *id, int p, int q)
{
    int i, j;
    for (i = p; i != *(id + i); i = *(id + i));
    for (j = q; j != *(id + j); j = *(id + j));
    if (i != j)
        *(id + i) = j;
}

  测试时可以采用书上的例子:
      这里写图片描述

 

posted @ 2017-01-01 22:36  jenny1000000  阅读(326)  评论(0编辑  收藏  举报