小米:朋友圈,并查集

33 篇文章 0 订阅


题目:假如已知有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属于另一个朋友圈,结果为两个朋友圈。

知识点:并查集。

代码:

#include<iostream>

using namespace std;

class friends{
public:
    friends(int n);//构造函数

    friends(const friends& f);//复制构造函数

    friends& operator=(const friends& f);//赋值构造函数

    ~friends();//析构函数

    int find(int x);
    void merge(int x, int y);
    int friendsCircles(int n, int m, int r[][2]);
private:
    int _n;
    int* _set;
};

friends::friends(int n):_n(n), _set(new int[n+1]){//构造函数,n+1是因为数组的第0个元素没有使用,所以n个元素需要申请n+1个空间
    cout << "调用构造函数开始!" << endl;
    int i;
    for(i = 1; i <= n; ++i)
        _set[i] = i;
    cout << "调用构造函数结束!" << endl;
}

friends::friends(const friends& f){//深复制
    cout << "调用复制构造函数开始!" << endl;
    _n = f._n;
    _set = new int[_n+1];
    memcpy(_set, f._set, (f._n+1) * sizeof(int));
    cout << "调用复制构造函数结束!" << endl;
}

friends& friends::operator=(const friends& f){
    if(&f != this){
        friends tempFriends(f);
        int *pTemp = tempFriends._set;
        tempFriends._set = _set;
        _set = pTemp;
    }
    return *this;
}

friends::~friends(){//析构函数
    cout << "调用析构函数开始!" << endl;
    delete[] _set;
    cout << "调用析构函数结束!" << endl;
}

int friends::find(int x){
    cout << "调用find函数开始!" << endl;
    int i, j, r;

    r = x;
    while(r != _set[r])//找到代表
        r = _set[r];

    i = x;
    while(i != r){//压缩路径
        j = _set[i];
        _set[i] = r;
        i = j;
    }
    cout << "调用find函数结束!" << endl;
    return r;
}
void friends::merge(int x, int y){
    cout << "调用merge函数开始!" << endl;
    int parentX = find(x);
    int parentY = find(y);

    if(parentX < parentY)//大 -> 小
        _set[parentY] = parentX;
    else
        _set[parentX] = parentY;
    cout << "调用merge函数结束!" << endl;
}

int friends::friendsCircles(int n, int m, int r[][2]){
    cout << "调用friendsCircles函数开始!" << endl;
    int i;
    int count = 0;
    
    for(i = 0; i < m; ++i)
        merge(r[i][0], r[i][1]);
    
    for(i = 1; i <= n; ++i){
        if(_set[i] == i)
            ++count;
    }
    cout << "调用friendsCircles函数结束!" << endl;
    return count;
}

void test1(){//测试在堆上实例化对象
    int r[][2] = {{1,2},{2,3},{4,5},{5,9},{6,2},{7,8}};
    int n = 9;
    int m = 6;
    friends *f = new friends(n);//f在堆上
    int count = f->friendsCircles(n, m, r);
    cout << "朋友圈的个数:" << count << endl;
    delete f;//因为f在堆上,所以程序结束时,不会自动调用friends的析构函数,只有用delete时,才调用析构函数
}
void test2(){//测试在栈上实例化对象
    int r[][2] = {{1,2},{2,3},{4,5},{5,9},{6,2},{7,8}};
    int n = 9;
    int m = 6;
    friends f(n);//f在栈上
    int count = f.friendsCircles(n, m, r);
    cout << "朋友圈的个数:" << count << endl;//因为f在栈上,所以程序结束时,会自动调用friends的析构函数。
}
void test3(){//测试复制函数
    int r[][2] = {{1,2},{2,3},{4,5},{5,9},{6,2},{7,8}};
    int n = 9;
    int m = 6;
    friends f(n);//f在栈上
    friends ff(f);
    int count = ff.friendsCircles(n, m, r);
    cout << "朋友圈的个数:" << count << endl;
}
void test4(){//测试赋值函数
    int r[][2] = {{1,2},{2,3},{4,5},{5,9},{6,2},{7,8}};
    int n = 9;
    int m = 6;
    friends f(n);//f在栈上
    friends ff(n+2);
    ff = f;
    int count = ff.friendsCircles(n, m, r);
    cout << "朋友圈的个数:" << count << endl;
}
int main(){
    test1();
    //test2();
    //test3();
    //test4();
    return 0;
}




这里我写了一个比较完全的类,由于类包含了指针成员,所以需要自己写 析构函数,这又导致需要自己写复制构造函数赋值构造函数三法则)。

下一篇文章我讲总结一下我在写这些代码时遇到的一些 尴尬问题!

关于带指针成员的类的 书写方法,建议参考: http://www.cnblogs.com/lucy-lizhi/p/6551308.html

大牛写的很详细,附有代码!



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值