template < class T, class Alloc = allocator> class forward_list;
前向链表是序列容器,使固定时间插入和擦除操作序列内的任何地方。
前向链表的实现方式和单链表相同;单链表可以存储所包含的每个元素在不同的和无关的存储位置。
在序列中顺序保存每个元素指向下一个元素的关联。
forward_list容器与list容器的主要设计区别是list保持内部唯一的一个链接到下一个元素,而后者则保持每个元素的两个链接:一个指向下一个元素和一个前一个。允许高效在两个方向迭代,但每个元素的消耗额外的存储空间,并轻微较高的时间开销插入和删除元素的迭代。forward_list对象,从而比list对象更有效率,虽然他们只能向前遍历。
与其他的基本标准序列容器(array,vector和deque)相比,forward_list一般在容器内的任何位置中的元素的插入、提取和移动操作效率更高,因此在算法中较密集的使用这些操作,例如排序算法。
相比其他序列容器,forward_lists的主要缺点是缺乏直接访问他们的位置的元素,例如,要进入第六个元素在forward_list的一个遍历从一开始就到那个位置,这需要线性时间之间的距离。他们也消耗了一些额外的内存保持连接信息相关联的每个元素(这可能是一个小型的元素的大链表的重要因素)。
考虑到forward_list类模板设计的性能:根据设计,它是作为一个简单的手写C风格的单链表一样高效,实际上是仅有的一个标准容器故意缺乏其大小的成员函数是出于效率的考虑。由于其作为一个链表的性质,有一个大小成员在固定的时间,需要保持一个内部的计数器保存其大小(和链表一样)。这会消耗一些额外的存储和使插入和删除操作,效率较低。为了获得一个forward_list对象的大小,可以用其开始和结束,这是一个线性时间的操作距离算法。
在一个严格的线性序列中序列容器的元素是有序的。个别元素的访问是通过他们在这个序列中的位置。
每个元素保持如何找到下一个元素的信息,允许常量时间在特定元素(甚至整个范围)后进行插入和擦除操作,但没有直接随机存取。
容器使用一个分配器对象动态地处理其存储需求。
1、
(构造函数)
|
构造 forward_list (公开成员函数)
从各种数据源构造新容器,可选地使用用户提供的分配器
1) 默认构造函数。构造空容器。
2) 构造拥有
count 个有值
value 的元素的容器。
3) 构造拥有个
count 默认插入的
T 实例的容器。不进行复制。
4) 构造拥有范围
[first, last) 内容的容器。
5) 复制构造函数。构造拥有
other 内容的容器。若不提供
alloc ,则如同通过调用
std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator()) 获得分配器。
6) 移动构造函数。用移动语义构造拥有
other 内容的容器。分配器通过属于
other 的分配器移动构造获得。
7) 有分配器扩展的移动构造函数。将
alloc 用作新容器的分配器,从
other 移动内容;若
alloc != other.get_allocator() ,则它导致逐元素移动。
8) 构造拥有 initializer_list
init 内容的容器。
参数
复杂度
1) 常数
2-3) 与
count 成线性
4) 与
first 和
last 的距离成线性
5) 与
other 的大小成线性
6) 常数。
7) 若
alloc != other.get_allocator() 则为线性,否则为常数。
8) 与
init 的大小成线性。
异常 到 注意 在容器移动构造(重载 (6) )后,指向 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(析构函数)
|
析构 forward_list (公开成员函数) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
operator=
|
赋值给容器 (公开成员函数)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assign
|
将值赋给容器 (公开成员函数)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_allocator
|
返回相关的分配器 (公开成员函数)
返回与容器关联的分配器。 参数(无) 返回值关联的分配器。 复杂度常数。 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#include
#include
#include
using namespace std;
//队列重载<<
template
ostream& operator<<(ostream& s, const forward_list& v)
{
s.put('[');
char comma[3] = { '\0', ' ', '\0' };
for (const auto& e : v) {
s << comma << e;
comma[0] = ',';
}
return s << ']';
}
int main()
{
forward_listlst{1,2,3,4,5,6};
cout << "lst:" << lst << endl;
forward_listlst1(lst.begin(), lst.end());
cout << "lst1:" << lst1 << endl;
//复制构造
forward_listlst2(lst);
cout << "lst2:" << lst2 << endl;
forward_listlst3(5, "AB");
cout << "lst3:" << lst3 << endl;
forward_listnum1{ 1, 2, 3, 4, 5, 6 };
forward_listnum2;
forward_listnum3;
cout << "num1:" << num1 << endl;
// 复制赋值会从 nums1 复制数据到 nums2
num2 = num1;
cout << "num2:" << num2 << endl;
// 移动赋值会从 nums1 移动数据到 nums3
num3 = move(num2);
cout << "num3:" << num3 << endl;
forward_listch;
ch.assign(6, '*');
cout << "ch:" << ch << endl;
//重新初始化对象
num1.assign(2, 6);
cout << "num1:" << num1 << endl;
//
forward_listch1;
ch1.assign(ch.begin(), ch.end());
cout << "ch1:" << ch1 << endl;
forward_list mylst;
int * p;
unsigned int i;
//分配数组5个元素的空间用于deque分配器
p = mylst.get_allocator().allocate(5);
// 空间中赋值
for (i = 0; i<5; i++)
mylst.get_allocator().construct(&p[i], i);
cout << "The allocated array contains:";
for (i = 0; i<5; i++)
cout << ' ' << p[i];
cout << '\n';
// 销毁空间
for (i = 0; i<5; i++)
mylst.get_allocator().destroy(&p[i]);
lst.get_allocator().deallocate(p, 5);
system("pause");
return 0;
}
2、
元素访问 |
||||||||||
front
|
访问第一个元素 (公开成员函数)
返回到容器首元素的引用。 在空容器上对 参数(无) 返回值到首元素的引用 复杂度常数 注意 对于容器 |
注意无operator[ ] 、at、 back、函数
3、
迭代器 |
|||||||||||||
before_begin
cbefore_begin |
返回指向第一个元素之前迭代器 (公开成员函数)
返回指向首元素前一元素的迭代器。此元素表现为占位符,试图访问它会导致未定义行为。仅有的使用情况是在函数 insert_after() 、 emplace_after() 、 erase_after() 、 splice_after() 和迭代器自增中:自增始前迭代器准确地给出与从 begin()/cbegin() 获得者相同的迭代器。 参数(无) 返回值指向首元素前一元素的迭代器。 复杂度常数。 |
||||||||||||
begin
cbegin |
返回指向容器第一个元素的迭代器 (公开成员函数)
返回指向容器首元素的迭代器。 若容器为空,则返回的迭代将等于 end() 。 参数(无) 返回值指向首元素的迭代器 复杂度常数 |
||||||||||||
end
cend |
返回指向容器尾端的迭代器 (公开成员函数)
返回指向后随容器最后元素的元素的迭代器。 此元素表现为占位符;试图访问它导致未定义行为。 参数(无) 返回值指向后随最后元素的迭代器。 复杂度常数。 |
#include
#include
#include
using namespace std;
int main()
{
forward_liststr{"aba","asd","sdf","efs","efs","www"};
//迭代器
forward_list::iterator iter = str.begin();
for (; iter != str.end();)
{
cout << *iter++ << ' ';
}
cout << endl;
//常迭代器
forward_list::const_iterator iter1 = str.begin();
for (; iter1 != str.end();)
{
cout << *iter1++ << ' ';
}
cout << endl;
//返回指向首元素前一元素的迭代器
str.insert_after(str.before_begin(), "66666");
cout <
4、
容量 |
||||||||||
empty
|
检查容器是否为空 (公开成员函数)
检查容器是否无元素,即是否 begin() == end() 。 参数(无) 返回值若容器为空则为 true ,否则为 false 复杂度常数。 |
|||||||||
max_size
|
返回可容纳的最大元素数 (公开成员函数)
返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。 参数(无) 返回值元素数量的最大值。 复杂度常数。 注意 此值典型地反映容器大小上的理论极限。运行时,容器的大小可能被可用 RAM 总量限制到小于 |
#include
#include
#include
using namespace std;
int main()
{
srand(time(0));
forward_list ch{'a','b','c','d','e','f'};
if (ch.empty() == 0)
cout << "ch is null" << endl;
ch.resize(20);
//容器可保有的元素最大数量
cout << "ch max_size:" << ch.max_size() << endl;
system("pause");
return 0;
}
5、
修改器 |
||||||||||||||||||||||||||||||||||||||||
clear
|
清除内容 (公开成员函数)
从容器移除所有元素。 非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器保持合法。 参数(无) 返回值(无) 复杂度与容器大小,即元素数成线性。 |
|||||||||||||||||||||||||||||||||||||||
insert_after
|
在某个元素后插入新元素 (公开成员函数)
在容器中的指定位置后插入元素。
1-2) 在
pos 所指向的元素后插入
value
3) 在
pos 所指向的元素后插入
value 的
count 个副本
4) 在
pos 所指向的元素后插入来自范围
[first, last) 的元素。 若
first 与
last 是指向
*this 中的迭代器则行为未定义。
5) 插入来自 initializer_list
ilist 的元素。
没有引用和迭代器被非法化。 参数
返回值
1-2) 指向被插入元素的迭代器。、
3) 指向最后被插入元素的迭代器,或若
count==0 则为
pos 。
4) 指向最后被插入元素的迭代器,或若
first==last 则为
pos 。
5) 指向最后被插入元素的迭代器,或若
ilist 为空则为
pos 。
异常 若在 复杂度
1-2) 常数。
3) 与
count 成线性
4) 与
std::distance(first, last) 成线性
5) 与
ilist.size() 成线性
|
|||||||||||||||||||||||||||||||||||||||
emplace_after
|
在元素后原位构造元素 (公开成员函数)
在容器中的指定位置后插入新元素。原位构造元素,即不进行复制或移动操作。准确地以与提供给函数者相同的参数调用元素的构造函数。 没有引用和迭代器被非法化。 参数
返回值指向新元素的迭代器。 复杂度常数。 异常若抛出任何异常(例如由构造函数),则容器留在未修改状态,如同从未调用过此函数(强异常保证)。 参阅 |
|||||||||||||||||||||||||||||||||||||||
erase_after
|
擦除元素后的元素 (公开成员函数)
从容器移除指定元素。
1) 移除后随
pos 的元素。
2) 移除范围
(first; last) 中的元素。
参数
返回值
1) 指向后随被擦除元素的迭代器,或若不存在这种元素则为
end() 。
2)
last
复杂度
1) 常数。
2) 与
first 和
last 之间的距离成线性。
|
|||||||||||||||||||||||||||||||||||||||
push_front
|
插入元素到容器起始 (公开成员函数)
前附给定元素 没有引用和迭代器被非法化。 参数
返回值(无) 复杂度常数。 异常若抛出异常,则此函数无效果(强异常保证)。 |
|||||||||||||||||||||||||||||||||||||||
emplace_front
|
在容器头部就地构造元素 (公开成员函数)
插入新元素到容器起始。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 没有引用和迭代器被非法化。 参数
返回值
复杂度常数。 异常若抛异常,则此函数无效果(强异常保证)。 |
|||||||||||||||||||||||||||||||||||||||
pop_front
|
移除首元素 (公开成员函数)
移除容器首元素。若容器中无元素,则行为未定义。 指向被擦除元素的迭代器和引用被非法化。 参数(无) 返回值(无) 复杂度常数。 异常不抛出。 |
|||||||||||||||||||||||||||||||||||||||
resize
|
改变容器中可存储元素的个数 (公开成员函数)
重设容器大小以容纳 若当前大小大于 若当前大小小于
1) 则后附额外的 默认插入的元素
2) 则后附额外的
value 的副本
参数
返回值(无) 复杂度 与当前大小和 |
|||||||||||||||||||||||||||||||||||||||
swap
|
交换内容 (公开成员函数)
将内容与 所有迭代器和引用保持合法。在操作后,保有此容器中尾后值的迭代器指代此容器或另一容器是未指定的。
参数
返回值(无) 异常
复杂度常数。 |
#include
#include
#include
#include
#include
using namespace std;
int main()
{
forward_list str{"Hello","World"};
cout << "str: " << str.front() << endl;
str.clear();
if (!str.empty())
cout << "str: " << str.front() << endl;
forward_list mylist{1,2,3,4,5,6};
forward_list::iterator it = mylist.begin();
++it;
it = mylist.insert_after(it, 10); // 1 10 2 3 4 5
// "it" now points to the newly inserted 10
mylist.insert_after(it, 2, 20); // 1 20 20 10 2 3 4 5
// "it" no longer valid!
it = mylist.begin();
vector myvector(2, 30);
mylist.insert_after(it, myvector.begin(), myvector.end());
// 1 20 30 30 20 10 2 3 4 5
cout << "mylist contains:";
for (it = mylist.begin(); it != mylist.end(); ++it)
cout << ' ' << *it;
cout << '\n';
forward_list mylist1 = { 10, 20, 30 };
auto it1 = mylist1.emplace_after(mylist1.begin(), 100);
mylist1.emplace_after(it1, 200);
cout << "mylist1 contains:";
for (auto& x : mylist1)
cout << ' ' << x;
cout << '\n';
forward_list str1{"Hello","World"};
cout << "str1: " << str1.front() << endl;
if (!str1.empty())
cout << "str1: " << str1.front() << endl;
forward_list arr{ 1, 2, 3, 4, 5, 6 };
for (forward_list::iterator it = arr.begin(); it != arr.end(); it++)
cout << *it << ' ';
cout << endl;
//移除首元素
arr.pop_front();
cout << "pop_front:" << endl;
for (forward_list::iterator it = arr.begin(); it != arr.end(); it++)
cout << *it << ' ';
cout << endl;
//交换
forward_listarr1(5, 9);
arr1.swap(arr);
for (forward_list::iterator it = arr.begin(); it != arr.end(); it++)
cout << *it << ' ';
cout << endl;
//首元素插入
arr.emplace_front(66);
arr.emplace_front(66);
arr.emplace_front(66);
cout << "emplace_front:" << endl;
for (forward_list::iterator it = arr.begin(); it != arr.end(); it++)
cout << *it << ' ';
cout << endl;
system("pause");
return 0;
}
6、
操作 |
||||||||||||||||||||||||||||||||||
merge
|
合并二个已排序列表 (公开成员函数)
归并二个已排序链表为一个。链表应以升序排序。 不复制元素。操作后容器 此操作是稳定的:对于二个链表中的等价元素,来自 参数
返回值(无) 异常若抛出异常,则此函数无效果(强异常保证),除非异常来自比较函数。 复杂度至多 std::distance(begin(), end()) + std::distance(other.begin(), other.end()) - 1 次比较。 |
|||||||||||||||||||||||||||||||||
splice_after
|
从另一 forward_list 移动元素 (公开成员函数)
从另一 不复制元素。
1) 从
other 移动所有元素到
*this 。元素被插入到
pos 所指向的元素后。操作后
other 变为空。若
this == &other 则行为未定义。
2) 从
other 移动后随
it 的迭代器所指向的元素到
*this 。元素被插入到
pos 所指向的元素后,若
pos==it 或若
pos==++it 则无效果。
3) 从
other 移动范围
(first, last) 中的元素到
*this 。元素被插入到
pos 所指向的元素后。不移动
first 所指向的元素。若
pos 是范围
(first,last) 中的元素则行为未定义。
参数
返回值(无) 复杂度
1) 与
other 的大小成线性
2) 常数
3) 与
std::distance(first, last) 成线性
|
|||||||||||||||||||||||||||||||||
remove
remove_if |
移除满足特定标准的元素 (公开成员函数)
移除所有满足特定标准的元素。第一版本移除所有等于 参数
返回值(无) 复杂度与容器大小成线性 |
|||||||||||||||||||||||||||||||||
reverse
|
将该链表的所有元素的顺序反转 (公开成员函数)
逆转容器中的元素顺序。不非法化任何引用或迭代器。 参数(无) 返回值(无) 参数与容器大小成线性 |
|||||||||||||||||||||||||||||||||
unique
|
删除连续的重复元素 (公开成员函数)
从容器移除所有相继的重复元素。只留下相等元素组中的第一个元素。第一版本用 参数
返回值(无) 复杂度与容器大小成线性 |
|||||||||||||||||||||||||||||||||
sort
|
对元素进行排序 (公开成员函数)
以升序排序元素。保持相等元素的顺序。第一版本用 operator< 比较元素,第二版本用给定的比较函数 若抛出异常,则 *this 中元素顺序未指定。 参数
返回值(无) 复杂度大约 N log N 次比较,其中 N 是表中的元素数。 注意 std::sort 要求随机访问迭代器且不能用于 |
#include
#include
using namespace std;
template
ostream&operator<<(ostream&s, const forward_list&list)
{
for (auto &i : list)
{
s << " " << i;
}
return s;
}
int main()
{
forward_listlist1{ 1, 6, 3, 6, 2, 8 };
forward_listlist2{ 7, 4, 2, 8, 6, 4, 9 };
//列表元素排序
list1.sort();
list2.sort();
cout << "list1:" << list1 << endl;
cout << "list2:" << list2 << endl;
list1.merge(list2);
cout << "list1 merge:" << list1 << endl;
advance(list1.begin(), 0);
cout << "list1 advace:" << list1 << endl;
//从一个 list 转移元素给另一个。
//不复制或移动元素,仅重指向链表结点的内部指针。
list1.splice_after(list1.cbegin(), list2);//将list2所有元素放置到list1中
cout << "list1:" << list1 << endl;
cout << "list2:" << list2 << endl;
////将list1所有元素放置到list2中
list2.splice_after(list2.before_begin(), list1, list1.cbegin(), list1.cend());
cout << "list1:" << list1 << endl;
cout << "list2:" << list2 << endl;
list2.remove(6);// 移除所有等于 6的元素
cout << "list2:" << list2 << endl;
list2.remove_if([](int n){ return n > 6; }); // 移除全部大于 6 的元素
cout << "list2:" << list2 << endl;
//列表反转
list2.reverse();
cout << "list2:" << list2 << endl;
//从容器移除所有相继的重复元素。
list2.unique();
cout << "list2:" << list2 << endl;
system("pause");
return 0;
}
7、
operator==
operator!= operator< operator<= operator> operator>= |
按照字典顺序比较 forward_list 中的值 (函数模板)
比较二个容器的内容。
1-2) 检查
lhs 与
rhs 的内容是否相等,即是否
lhs.size() == rhs.size() 且每个
lhs 中的元素与
rhs 的同位置元素比较相等。
3-6) 按字典序比较
lhs 与
rhs 的内容。按照等价于
std::lexicographical_compare 的函数进行比较。
参数
返回值
1) 若容器内容相等则为
true ,否则为
false
2) 若容器内容不相等则为
true ,否则为
false
3) 若
lhs 的内容按字典序
小于
rhs 的内容则为
true ,否则为
false
4) 若
lhs 的内容按字典序
小于或
等于
rhs 的内容则为
true ,否则为
false
5) 若
lhs 的内容按字典序
大于
rhs 的内容则为
true ,否则为
false
6) 若
lhs 的内容按字典序
大于或
等于
rhs 的内容则为
true ,否则为
false
复杂度与容器大小成线性 |
||||||||||||||||||||||||||||||
std::swap
(std::forward_list)
(C++11)
|
特化 std::swap 算法 (函数模板)
为 std::forward_list 特化 std::swap 算法。交换 参数
返回值(无) 复杂度常数。 异常
|
//deque comparisons
#include
#include
using namespace std;
int main()
{
forward_list a = { 10, 20, 30 };
forward_list b = { 10, 20, 30 };
forward_list c = { 30, 20, 10 };
if (a == b)
cout << "a and b are equal\n";
if (b != c)
cout << "b and c are not equal\n";
if (bb)
cout << "c is greater than b\n";
if (a <= b)
cout << "a is less than or equal to b\n";
if (a >= b)
cout << "a is greater than or equal to b\n";
system("pause");
return 0;
}
swap:
//swap (deque overload)
#include
#include
using namespace std;
int main()
{
unsigned int i;
forward_list foo(3, 100); // three ints with a value of 100
forward_list bar(5, 200); // five ints with a value of 200
swap(foo, bar);
cout << "foo contains:";
for (forward_list::iterator it = foo.begin(); it != foo.end(); ++it)
cout << ' ' << *it;
cout << '\n';
cout << "bar contains:";
for (forward_list::iterator it = bar.begin(); it != bar.end(); ++it)
cout << ' ' << *it;
cout << '\n';
system("pause");
return 0;
}