C++的forward_list
参考:
http://blog.csdn.net/devourheavens/article/details/7497172
http://zh.cppreference.com/w/cpp/container/forward_list
forward_list
<forward_list>
template < class T, class Alloc = allocator<T> > class forward_list;
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=
|
赋值给容器 (公开成员函数)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
将值赋给容器 (公开成员函数)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回相关的分配器 (公开成员函数)
返回与容器关联的分配器。 参数(无) 返回值关联的分配器。 复杂度常数。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
example
1 #include<iostream>
2 #include<string>
3 #include<forward_list>
4
5 using namespace std;
6
7 //队列重载<<
8 template<typename T>
9 ostream& operator<<(ostream& s, const forward_list<T>& v)
10 {
11 s.put('[');
12 char comma[3] = { '\0', ' ', '\0' };
13 for (const auto& e : v) {
14 s << comma << e;
15 comma[0] = ',';
16 }
17 return s << ']';
18 }
19
20 int main()
21 {
22 forward_list<int>lst{1,2,3,4,5,6};
23
24 cout << "lst:" << lst << endl;
25
26 forward_list<int>lst1(lst.begin(), lst.end());
27 cout << "lst1:" << lst1 << endl;
28
29 //复制构造
30 forward_list<int>lst2(lst);
31 cout << "lst2:" << lst2 << endl;
32
33 forward_list<string>lst3(5, "AB");
34 cout << "lst3:" << lst3 << endl;
35
36 forward_list<int>num1{ 1, 2, 3, 4, 5, 6 };
37 forward_list<int>num2;
38 forward_list<int>num3;
39
40
41 cout << "num1:" << num1 << endl;
42 // 复制赋值会从 nums1 复制数据到 nums2
43 num2 = num1;
44 cout << "num2:" << num2 << endl;
45
46 // 移动赋值会从 nums1 移动数据到 nums3
47 num3 = move(num2);
48 cout << "num3:" << num3 << endl;
49
50 forward_list<char>ch;
51 ch.assign(6, '*');
52 cout << "ch:" << ch << endl;
53
54 //重新初始化对象
55 num1.assign(2, 6);
56 cout << "num1:" << num1 << endl;
57
58 //
59 forward_list<char>ch1;
60 ch1.assign(ch.begin(), ch.end());
61 cout << "ch1:" << ch1 << endl;
62
63 forward_list<int> mylst;
64 int * p;
65 unsigned int i;
66
67 //分配数组5个元素的空间用于deque分配器
68 p = mylst.get_allocator().allocate(5);
69
70 // 空间中赋值
71 for (i = 0; i<5; i++)
72 mylst.get_allocator().construct(&p[i], i);
73
74 cout << "The allocated array contains:";
75 for (i = 0; i<5; i++)
76 cout << ' ' << p[i];
77 cout << '\n';
78
79 // 销毁空间
80 for (i = 0; i<5; i++)
81 mylst.get_allocator().destroy(&p[i]);
82 lst.get_allocator().deallocate(p, 5);
83
84
85 system("pause");
86 return 0;
87 }
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 |
返回指向容器尾端的迭代器 (公开成员函数)
返回指向后随容器最后元素的元素的迭代器。 此元素表现为占位符;试图访问它导致未定义行为。
参数(无) 返回值指向后随最后元素的迭代器。 复杂度常数。 |
example
1 #include<iostream>
2 #include<string>
3 #include<forward_list>
4
5 using namespace std;
6
7 int main()
8 {
9 forward_list<string>str{"aba","asd","sdf","efs","efs","www"};
10
11 //迭代器
12 forward_list<string>::iterator iter = str.begin();
13 for (; iter != str.end();)
14 {
15 cout << *iter++ << ' ';
16 }
17 cout << endl;
18
19 //常迭代器
20 forward_list<string>::const_iterator iter1 = str.begin();
21 for (; iter1 != str.end();)
22 {
23 cout << *iter1++ << ' ';
24 }
25 cout << endl;
26
27 //返回指向首元素前一元素的迭代器
28
29 str.insert_after(str.before_begin(), "66666");
30 cout <<str.front()<< endl;
31
32 system("pause");
33 return 0;
34 }
4、容量
容量 |
||||||||||
empty
|
检查容器是否为空 (公开成员函数)
检查容器是否无元素,即是否 begin() == end() 。 参数(无) 返回值若容器为空则为 true ,否则为 false 复杂度常数。 |
|||||||||
max_size
|
返回可容纳的最大元素数 (公开成员函数)
返回根据系统或库实现限制的容器可保有的元素最大数量,即对于最大容器的 std::distance(begin(), end()) 。 参数(无) 返回值元素数量的最大值。 复杂度常数。 注意此值典型地反映容器大小上的理论极限。运行时,容器的大小可能被可用 RAM 总量限制到小于 |
example
1 #include<iostream>
2 #include<forward_list>
3 #include<ctime>
4 using namespace std;
5
6 int main()
7 {
8 srand(time(0));
9 forward_list<char> ch{'a','b','c','d','e','f'};
10
11
12
13 if (ch.empty() == 0)
14 cout << "ch is null" << endl;
15
16 ch.resize(20);
17 //容器可保有的元素最大数量
18 cout << "ch max_size:" << ch.max_size() << endl;
19
20
21 system("pause");
22 return 0;
23 }
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
|
交换内容 (公开成员函数)
将内容与 所有迭代器和引用保持合法。在操作后,保有此容器中尾后值的迭代器指代此容器或另一容器是未指定的。
参数
返回值(无) 异常
复杂度常数。 |
example
1 #include<iostream>
2 #include<string>
3 #include<forward_list>
4 #include<ctime>
5 #include<vector>
6 using namespace std;
7
8 int main()
9 {
10 forward_list<string> str{"Hello","World"};
11
12 cout << "str: " << str.front() << endl;
13 str.clear();
14 if (!str.empty())
15 cout << "str: " << str.front() << endl;
16
17
18 forward_list<int> mylist{1,2,3,4,5,6};
19
20 forward_list<int>::iterator it = mylist.begin();
21 ++it;
22
23 it = mylist.insert_after(it, 10); // 1 10 2 3 4 5
24 // "it" now points to the newly inserted 10
25
26 mylist.insert_after(it, 2, 20); // 1 20 20 10 2 3 4 5
27 // "it" no longer valid!
28
29 it = mylist.begin();
30
31 vector<int> myvector(2, 30);
32 mylist.insert_after(it, myvector.begin(), myvector.end());
33 // 1 20 30 30 20 10 2 3 4 5
34
35 cout << "mylist contains:";
36 for (it = mylist.begin(); it != mylist.end(); ++it)
37 cout << ' ' << *it;
38 cout << '\n';
39
40 forward_list<int> mylist1 = { 10, 20, 30 };
41
42 auto it1 = mylist1.emplace_after(mylist1.begin(), 100);
43 mylist1.emplace_after(it1, 200);
44
45 cout << "mylist1 contains:";
46 for (auto& x : mylist1)
47 cout << ' ' << x;
48 cout << '\n';
49
50
51 forward_list<string> str1{"Hello","World"};
52
53 cout << "str1: " << str1.front() << endl;
54 if (!str1.empty())
55 cout << "str1: " << str1.front() << endl;
56
57
58
59
60 forward_list<int> arr{ 1, 2, 3, 4, 5, 6 };
61 for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
62 cout << *it << ' ';
63 cout << endl;
64
65
66
67 //移除首元素
68 arr.pop_front();
69 cout << "pop_front:" << endl;
70 for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
71 cout << *it << ' ';
72 cout << endl;
73
74 //交换
75 forward_list<int>arr1(5, 9);
76 arr1.swap(arr);
77
78 for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
79 cout << *it << ' ';
80 cout << endl;
81
82 //首元素插入
83 arr.emplace_front(66);
84 arr.emplace_front(66);
85 arr.emplace_front(66);
86 cout << "emplace_front:" << endl;
87 for (forward_list<int>::iterator it = arr.begin(); it != arr.end(); it++)
88 cout << *it << ' ';
89 cout << endl;
90
91
92
93 system("pause");
94 return 0;
95 }
6、操作
example
1 #include<iostream>
2 #include<forward_list>
3
4 using namespace std;
5
6 template<typename T>
7 ostream&operator<<(ostream&s, const forward_list<T>&list)
8 {
9 for (auto &i : list)
10 {
11 s << " " << i;
12 }
13 return s;
14 }
15 int main()
16 {
17 forward_list<int>list1{ 1, 6, 3, 6, 2, 8 };
18 forward_list<int>list2{ 7, 4, 2, 8, 6, 4, 9 };
19
20 //列表元素排序
21 list1.sort();
22 list2.sort();
23
24 cout << "list1:" << list1 << endl;
25 cout << "list2:" << list2 << endl;
26 list1.merge(list2);
27 cout << "list1 merge:" << list1 << endl;
28
29
30 advance(list1.begin(), 0);
31 cout << "list1 advace:" << list1 << endl;
32 //从一个 list 转移元素给另一个。
33 //不复制或移动元素,仅重指向链表结点的内部指针。
34 list1.splice_after(list1.cbegin(), list2);//将list2所有元素放置到list1中
35 cout << "list1:" << list1 << endl;
36 cout << "list2:" << list2 << endl;
37
38 将list1所有元素放置到list2中
39 list2.splice_after(list2.before_begin(), list1, list1.cbegin(), list1.cend());
40 cout << "list1:" << list1 << endl;
41 cout << "list2:" << list2 << endl;
42
43 list2.remove(6);// 移除所有等于 6的元素
44 cout << "list2:" << list2 << endl;
45
46 list2.remove_if([](int n){ return n > 6; }); // 移除全部大于 6 的元素
47 cout << "list2:" << list2 << endl;
48
49 //列表反转
50 list2.reverse();
51 cout << "list2:" << list2 << endl;
52
53 //从容器移除所有相继的重复元素。
54 list2.unique();
55 cout << "list2:" << list2 << endl;
56
57 system("pause");
58 return 0;
59 }
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 ,否则为 false4) 若
lhs 的内容按字典序 小于或 等于 rhs 的内容则为 true ,否则为 false5) 若
lhs 的内容按字典序 大于 rhs 的内容则为 true ,否则为 false6) 若
lhs 的内容按字典序 大于或 等于 rhs 的内容则为 true ,否则为 false复杂度与容器大小成线性 |
||||||||||||||||||||||||||||||
std::swap(std::forward_list)
(C++11)
|
特化 std::swap 算法 (函数模板)
为 std::forward_list 特化 std::swap 算法。交换 参数
返回值(无) 复杂度常数。 异常
|
example
1 //deque comparisons
2 #include <iostream>
3 #include <forward_list>
4 using namespace std;
5 int main()
6 {
7 forward_list<int> a = { 10, 20, 30 };
8 forward_list<int> b = { 10, 20, 30 };
9 forward_list<int> c = { 30, 20, 10 };
10
11 if (a == b)
12 cout << "a and b are equal\n";
13 if (b != c)
14 cout << "b and c are not equal\n";
15 if (b<c)
16 cout << "b is less than c\n";
17 if (c>b)
18 cout << "c is greater than b\n";
19 if (a <= b)
20 cout << "a is less than or equal to b\n";
21 if (a >= b)
22 cout << "a is greater than or equal to b\n";
23
24 system("pause");
25 return 0;
26 }
本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/14005971.html