8. O(1)时间求两个不相交集合的并集

  • 《算法导论》10.2-6 动态集合操作Union以两个不相交集合S1和S2作为输入,并返回集合S = S1∪S2。该操作通常会破坏集合S1和S2。试说明如何选用一种合适的表类数据结构,来支持O(1)时间的Union操作。

    O(1)时间能干嘛?不能移动元素,只能改改指针,所以采用链表最合适,这道题采用单链表就够了。

    我在之前定义的SingleLinkedList类型里面声明一个friend function。注意声明为friend 的class or function不可以是template,必须是实例化类型或方法,所以用friend SingleLinkedList Union<Object>(SingleLinkedList&& lhs,SingleLinkedList&& rhs);而不是friend SingleLinkedList Union(SingleLinkedList&& lhs, SingleLinkedList&& rhs);

//将模板函数Union声明为class SingleLinkedList的友元函数
template<typename Object> class SingleLinkedList;   //needed for parameters in Union

//forward declarations needed for friend declarations in SingleLinkedList
template<typename Object>
SingleLinkedList<Object> Union(SingleLinkedList<Object>&& lhs,
                              SingleLinkedList<Object>&& rhs);
template<typename Object>
class SingleLinkedList
{
    //in order to refer to a specific instantiation of the template function "Union", "<Object>" is needed
    friend SingleLinkedList Union<Object>(SingleLinkedList&& lhs,
                                  SingleLinkedList&& rhs);
    //...[main part of class definition ](https://www.cnblogs.com/meixiaogua/p/10175608.html)
}

//定义Union
/*我一开始把返回值定义成&&了,那样是不对的
因为函数Union返回相当于是在执行 SingleLinkedList<Object>&& temp = std::move(u);
u告诉我们自己的资源可以被偷走,然后把资源位置写到temp变量中,然后u的资源就被函数销毁了。
就相当于temp里面记录的资源位置还没来得及被人注意到,那个资源就失效了
正确的方法是定义返回值类型为SingleLinkedList<Object>*/
template<typename Object>
SingleLinkedList<Object> Union(SingleLinkedList<Object>&& lhs,
                              SingleLinkedList<Object>&& rhs)
{
    SingleLinkedList<Object> u(std::move(lhs));
    if(!rhs.empty())
    {
        u.sentinelPrev->next = rhs.sentinel->next;
        rhs.sentinelPrev->next = u.sentinel;
        u.sentinelPrev = rhs.sentinelPrev;
        rhs.sentinel->next = rhs.sentinelPrev = rhs.sentinel;
    }
    return std::move(u);
}

void testUnion()
{
    using namespace std;
    SingleLinkedList<int> a,b;
    for(int i = 0; i != 4; ++i)
        a.push_back(i);
    for(int i = 10; i != 14; ++i)
        b.push_back(i);
    auto r = Union(std::move(a),std::move(b));
    decltype(a) u(std::move(r));
    while(!u.empty())
    {
        cout << u.front() << " ";
        u.pop_front();
    }
    cout << endl;
}

//测试输出
0 1 2 3 10 11 12 13 

转载于:https://www.cnblogs.com/meixiaogua/p/10185914.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值