1.splice的几种用法
项目开发过程中,发现stl中的list有splice方法,而且splice方法还挺实用,可以很方便地对链表进行一些连接断开的操作。因此我们下面来详细总结并实测一下splice的几种用法。
list1.splice(iterator position, list2)
list1.splice(iterator position, list2, iterator i)
list1.splice(iterator position, list2, iterator first, iterator last)
splice有以上三种函数签名,其中
list1表示被拼接的列表,操作以后其结构会发生改变(如果有改变的话)
iterator position表示操作开始时list1的迭代器位置
list2为将其元素拼接到list1的列表。
iterator i是list2中要拼接的迭代器元素。
iterator first, iterator last则是list2中要拼接元素的第一个与最后一个。
下面我们通过几个实例来进行测试。
2.全部拼接
void run3() {
list<int> l1 = { 1, 2, 3 };
list<int> l2 = { 4, 5 };
list<int> l3 = { 6, 7, 8 };
// 将l2全部加入l1,插入的位置为l1的开头
l1.splice(l1.begin(), l2);
cout << "list l1 after splice operation" << endl;
for (auto ele : l1) cout << ele << " ";
cout << endl;
cout << "list l2 after splice operation" << endl;
cout << "l2.size is: " << l2.size() << endl;
// 将l1全部加入l3的末尾
l3.splice(l3.end(), l1);
// at the end of l3
cout << "list l3 after splice operation" << endl;
for (auto ele : l3) cout << ele << " ";
}
如果我们将上面的代码运行,最终将得到如下输出
list l1 after splice operation
4 5 1 2 3
list l2 after splice operation
l2.size is: 0
list l3 after splice operation
6 7 8 4 5 1 2 3
l1.splice(l1.begin(), l2);
这行代码,表示将l2全部拼接到l1,拼接的位置在l1的头位置。并且注意拼接完成以后,l2此时的size已经变为0。
同理当
l3.splice(l3.end(), l1);
这行代码执行以后,会将l1全部拼接到l3,拼接位置在l3的尾部。
3.拼接单个元素
void run4() {
list<int> mylist = {1, 2, 3, 4, 5};
list<int>::iterator needit;
for(auto it=mylist.begin(); it!=mylist.end(); it++) {
if (*it==3) needit = it;
}
mylist.splice(mylist.begin(), mylist, needit);
for(int ele: mylist) {
cout<<ele<<" ";
}
}
mylist.splice(mylist.begin(), mylist, needit);
重点解释一下上面这行代码。注意此时list2的位置,我们传入的跟list1相同,也即意味着我们操作的是同一个列表。我们想要做的事情是将列表中的某一个元素,移动到列表表头的位置。所以最后代码的输出为:
3 1 2 4 5
所以,用splice方法就可以达到我们上述的目的。这样的好处在于,简单不易出错,帮我们简化省略了链表中各种指针断链再重新链接的过程。
4.移动一段元素
上面解释的移动一个元素,如果我们想移动多个连续的一段元素,那么自然也可以采用类似的办法。
void run5() {
list<int> mylist = {1, 2, 3, 4, 5, 6, 7};
list<int>::iterator beginit, endit;
for(auto it=mylist.begin(); it!=mylist.end(); it++) {
if (*it==3) beginit = it;
if (*it==5) endit = it;
}
mylist.splice(mylist.begin(), mylist, beginit, endit);
for(int ele: mylist) {
cout<<ele<<" ";
}
}
具体原理跟上面类似,不再多做解释。最终代码输出为
3 4 1 2 5 6 7
从上面的测试代码不难看出,最终的last元素,不包含在移动范围之内。