zoukankan      html  css  js  c++  java
  • 并查集

         并查集是一种树形的数据结构,用来处理不相交的集合的合并和查询。原理是:先开辟一个和数据大小相等的数组a,数组数据初始化为-1,当数据x1,x2同属一个集合,将数组a[x2]加到a[x1]上,并将x1赋给a[x2],这样,如果检查的时候数组的值小于0,则为根节点,并且这个值的绝对值为这个集合元素的个数。如果检查的时候数组的值大于0,则不是根节点,数组的值为上一节点的数组的值。下面用一个例子说明。

    小米的校招题:
    朋友圈(25分)
    假如已知有n个人和m对好友关系(存于数字r)。如果两个人是直接或间接的好友(好友的好友的好友...),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈。
    假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1、2、3属于一个朋友圈,4、5属于另一个朋友圈,结果为2个朋友圈。
    最后请分析所写代码的时间、空间复杂度。评分会参考代码的正确性和效率。
    C/C++:
    int friends(int n , int m , int* r[]);

    //代码实现如下:

    #pragma once
    class unionFindset
    {
    public:

    //开辟一段和数组个数相等大小的数组空间
    unionFindset(size_t size)
    :_a(new int[size])
    , _size(size)
    {

    //将数组中数据元素都初始化为-1
    for (int i = 0; i < size; ++i)
    {
    _a[i] = -1;
    }
    }

    //合并
    void combine(int root1, int root2)
    {
    if (_a[root1] < 0 && _a[root2] < 0)
    {
    _a[root1] += _a[root2];
    _a[root2] = root1;
    }
    }
    //寻找根节点,即数组中元素小于0的元素
    int FindRoot(int child)
    {
    while (_a[child] >= 0)
    child = _a[child];
    return child;
    }

    int count()
    {
    int count = 0;
    for (int i = 0; i < _size; ++i)
    {
    if (_a[i]<=0)
    count++;
    }
    return count;
    }
    protected:
    int *_a;
    int _size;
    };

    int Friends(int n, int m, int r[][2])
    {
    assert(r);
    unionFindset us(n);
    for (int i = 0; i < m; ++i)
    {
    int first = r[i][0];
    int second = r[i][1];
    int root1 = us.FindRoot(first);
    int root2 = us.FindRoot(second);
    if (root1 != root2)
    {
    us.combine(root1, root2);
    }
    }

    //注意:这里count要减1,因为开辟的数组下标是从0开始的,而实际存取数据是从1开始的,因此要减1
    return us.count() -1;
    }

  • 相关阅读:
    win7与centos虚拟机的共享文件夹创建
    MySQL视图
    MySQL分区表与合并表
    PHP读写XML文件的四种方法
    备份与恢复
    MySQL日志
    MySQL锁问题
    优化数据库对象
    ActiveReport资料
    对ArrayList 进行深拷贝
  • 原文地址:https://www.cnblogs.com/qingjiaowoxiaoxioashou/p/5517405.html
Copyright © 2011-2022 走看看