并查集和(小米面试题)

并查集:
将N个不同的元素分成一组不相交的集合。
开始时,每个元素就是一个集合,然后按规律将两个集合进行合并。
原理:
两个数元素中选择一个元素作为根,让另一个元素对应下表的内容加到第一个元素对应下标的内容中,并把另一个元素下标对应内容变为第一个的元素。
(1)申请一块数组用以标记元素之间的关系
初始化
这里写图片描述

给定一个关系,用上图进行标记,如果两个元素之间不是同一个的根就把第二个元素当作下标取刚申请的数组中的内容加到第一个元素对应下标的内容中,最后负数 的个数就是大关系的个数。

单关系图:
这里写图片描述

多关系图:
这里写图片描述

面试题,可以使用并查集,代码在下面:
这里写图片描述

#include<iostream>
using namespace std;

class SearchSet
{
public:
    /*构造的时候申请一个数组,给他初始化为-1*/
    SearchSet(size_t size)
        :_size(size),
        _set(new int[size])
    {
        for (size_t i = 0; i < size; i++)
        {
            _set[i] = -1;
        }
    }


    int FindRoot(int child)
    {
        int parent = child;
        while (_set[parent]>=0)
        {
            parent = _set[parent];
        }
        return parent;
    }

    void Union(int x, int y)
    {
        int m=FindRoot(x);
        int n=FindRoot(y);
        if (m == n)
            return;
        else
        {
            _set[m] += _set[n];
            _set[n] = m;
        }

    }
    void Print()
    {
        for (size_t i = 0; i < _size; i++)
        {
            cout << _set[i] << " ";
        }
    }
    /*找出关系的总数*/
    int FriendCount()
    {
        int count = 0;
        for (size_t i = 0; i < _size; i++)
        {
            if (_set[i] < -1)//考虑没有关系0内有作用,就把0号下标对应的-1去掉
            {
                count++;
            }
        }
        return count;
    }

private:
    int *_set;
    size_t _size;
};



void testSearchSet()
{

    SearchSet s(10);
    s.Union(0, 6);
    s.Union(0, 7);
    s.Union(0, 8);
    s.Union(1, 4);
    s.Union(1, 9);
    s.Union(2, 3);
    s.Union(2, 5);
    s.Union(0, 1);
    s.Print();

}


/*小米面试题:*/
void Frient()
{
    const int M = 3;
    const int N = 2;
    int arr[M][N] = { { 1, 2 }, { 2, 3 }, { 4, 5 } };
    SearchSet s(6);
    for (int i = 0; i < M; i++)
    {
        s.Union(arr[i][0], arr[i][1]);
    }
    size_t count = s.FriendCount();
    cout << count<<endl;

}

int main()
{
    //testSearchSet();
    Frient();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值