《算法导论》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(SingleLinkedList&& lhs,SingleLinkedList&& rhs);而不是friend SingleLinkedList Union(SingleLinkedList&& lhs, SingleLinkedList&& rhs);。//将模板函数Union声明为class SingleLinkedList的友元函数 templateclass SingleLinkedList; //needed for parameters in Union //forward declarations needed for friend declarations in SingleLinkedList templateSingleLinkedListUnion(SingleLinkedList&& lhs, SingleLinkedList&& rhs); templateclass SingleLinkedList { //in order to refer to a specific instantiation of the template function "Union", "" is needed friend SingleLinkedList Union(SingleLinkedList&& lhs, SingleLinkedList&& rhs); //...[main part of class definition ](https://www.cnblogs.com/meixiaogua/p/10175608.html) } //定义Union /*我一开始把返回值定义成&&了,那样是不对的 因为函数Union返回相当于是在执行 SingleLinkedList&& temp = std::move(u); u告诉我们自己的资源可以被偷走,然后把资源位置写到temp变量中,然后u的资源就被函数销毁了。 就相当于temp里面记录的资源位置还没来得及被人注意到,那个资源就失效了 正确的方法是定义返回值类型为SingleLinkedList*/ templateSingleLinkedListUnion(SingleLinkedList&& lhs, SingleLinkedList&& rhs) { SingleLinkedListu(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; SingleLinkedLista,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