forward_list 内部以单项链表方式管理元素, 使用要包含头文件
#include <forward_list>
forward_list是一个行为受限的list,不能走回头路。凡是list没提供的功能,它都不提供。优点是占用内存小,操作速度快。
特性
forward_list与list的差异
(1) 只提供向前迭代器,不提供双向迭代器。这意味着,reverse_iterator之类的类型,rbegin,rend,crbegin,crend之类的成员都不能提供
(2) 不提供成员函数size()
(3) 没有指向最末元素的指针, 因此不提供 back(), push_back(), pop_back()
(4) 对于特定位置的插入删除操作, 都提供了特殊版本, 成员函数都带有一个后缀 _after, 例如 insert_after()取代insert()
(5) 提供 before_begin(), cbefore_begin(), 产生出第一个元素之前的一个虚拟位置,可被用来让带有_after后缀的算法交换第一个元素
除了这些差异, forward_list就像是一个list
[1] 不提供随机访问
[2] 在任何位置上插入删除操作都很快
[3] 插入删除,不会造成指向其他元素的指针,引用,迭代器失效
[4] forward_list提供了许多特殊成员函数用于搬移和移除元素,这些函数是一般算法的快速版。然而,只要涉及位置,必须传递给他们目标物的前一个位置
部分操作
c.front() | 返回第一个元素 |
c.push_front(elem) | 在头部插入elem的一个拷贝 |
c.pop_front() | 移除第一个元素 |
c.insert_after(pos,elem) | 插入一个elem拷贝与pos之后,返回新元素位置 |
c.insert_after(pos,n,elem) | 插入n个elem的拷贝于pos之后,并返回第一个新元素位置(返回pos如果没有新元素) |
c.insert_after(pos,beg,end) | 将[beg,end)区间的所有元素复制一份,插入pos位置之后,并返回第一个新元素位置 |
c.insert_after(pos,initlist) | |
c.emplace_after(pos,args...) | 在pos之后插入一个以args为初值的元素,并返回新元素的位置 |
c.emplace_front(args...) | 插入一个以args为初值的元素于起点,不返回任何东西 |
c.erase_after(pos) | 移除pos之后的元素,不返回任何东西 |
c.erase_after(beg,end) | 移除[beg,end)区间的所有元素,不返回任何东西 |
c.remove(val) | 移除所有值为val的元素 |
c.remove_if(op) | 移除所有“造成op(elem)结果为true”的元素 |
c.resize(num) | 将元素数量改为num |
c.resize(num,elem) | |
c.clear() | 删除所有元素 |
c.unique() | 删除相邻重复元素只留一个 |
c.unique(op) | |
c.splice_after(pos,c2) | 删除相邻都令op为true的元素只留一个 |
c.splice_after(pos,c2,c2pos) | 将c2所有元素move到c之内,迭代器pos之后 |
c.splice_after(pos,c2,c2beg,c2end) | 将c2内的c2pos所指元素转移到c内的pos所指位置(c和c2可以是同一容器) |
c.sort() | 以operator< 为准则对所有元素排序 |
c.sort(op) | 以op为准则对所有元素排序 |
c.merge(c2) | 假设c和c2都包含已排序元素,将c2全部元素move到c,并保证合并后所有元素已排序 |
c.merge(c2,op) | |
c.reverse() | 将所有元素反序 |
起始处插入删除元素
查找、移除或安插元素
#include <forward_list>
#include "print.hpp"
using namespace std;
int main()
{
forward_list<int> list = { 1, 2, 3, 4, 5, 97, 98, 99 };
// find the position before the first even element
auto posBefore = list.before_begin();
for (auto pos=list.begin(); pos!=list.end(); ++pos, ++posBefore) {
if (*pos % 2 == 0) {
break; // element found
}
}
// and insert a new element in front of the first even element
list.insert_after(posBefore,42);
PRINT_ELEMENTS(list);
}
等效查找方法, 使用便捷函数 next()
#include <iterator>
...
auto posBefore = list.before_begin();
for ( ; next(posBefore)!=list.end(); ++posBefore) {
if (*next(posBefore) % 2 == 0) {
break; // element found
}
}
自定义算法,找出“拥有特定值”或“满足某个特定条件”的元素的前一位置
template <typename InputIterator, typename Tp>
inline InputIterator
find_before (InputIterator first, InputIterator last, const Tp& val)
{
if (first==last) {
return first;
}
InputIterator next(first);
++next;
while (next!=last && !(*next==val)) {
++next;
++first;
}
return first;
}
template <typename InputIterator, typename Pred>
inline InputIterator
find_before_if (InputIterator first, InputIterator last, Pred pred)
{
if (first==last) {
return first;
}
InputIterator next(first);
++next;
while (next!=last && !pred(*next)) {
++next;
++first;
}
return first;
}
有了这些函数,就可以给出lambda找出所需位置
// find the position before the first even element
auto posBefore = find_before_if (list.before_begin(), list.end(),
[] (int i) {
return i%2==0;
});
// and insert a new element in front of it
list.insert_after(posBefore,42);
运用实例
#include <forward_list>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
void printLists (const string& s, const forward_list<int>& l1, const forward_list<int>& l2)
{
cout << s << endl;
cout << " list1: ";
copy (l1.cbegin(), l1.cend(), ostream_iterator<int>(cout," "));
cout << endl << " list2: ";
copy (l2.cbegin(), l2.cend(), ostream_iterator<int>(cout," "));
cout << endl;
}
int main()
{
// create two forward lists
forward_list<int> list1 = { 1, 2, 3, 4 };
forward_list<int> list2 = { 77, 88, 99 };
printLists ("initial:", list1, list2);
// insert six new element at the beginning of list2
list2.insert_after(list2.before_begin(),99);
list2.push_front(10);
list2.insert_after(list2.before_begin(), {10,11,12,13} );
printLists ("6 new elems:", list1, list2);
// insert all elements of list2 at the beginning of list1
list1.insert_after(list1.before_begin(), list2.begin(), list2.end());
printLists ("list2 into list1:", list1, list2);
// delete second element and elements after element with value 99
list2.erase_after(list2.begin());
list2.erase_after(find(list2.begin(), list2.end(), 99), list2.end());
printLists ("delete 2nd and after 99:", list1, list2);
// sort list1, assign it to list2, and remove duplicates
list1.sort();
list2 = list1;
list2.unique();
printLists ("sorted and unique:", list1, list2);
// merge both sorted lists into list1
list1.merge(list2);
printLists ("merged:", list1, list2);
}
-----------------------------------------------------------------------------------------
initial:
list1: 1 2 3 4
list2: 77 88 99
6 new elems:
list1: 1 2 3 4
list2: 10 11 12 13 10 99 77 88 99
list2 into list1:
list1: 10 11 12 13 10 99 77 88 99 1 2 3 4
list2: 10 11 12 13 10 99 77 88 99
delete 2nd and after 99:
list1: 10 11 12 13 10 99 77 88 99 1 2 3 4
list2: 10 12 13 10 99
sorted and unique:
list1: 1 2 3 4 10 10 11 12 13 77 88 99 99
list2: 1 2 3 4 10 11 12 13 77 88 99
merged:
list1: 1 1 2 2 3 3 4 4 10 10 10 11 11 12 12 13 13 77 77 88 88 99 99 99
list2: