C++11 中forward_list是一个单向链表,单向链表有其对应的有缺点吧。总体上其有缺点都不是很明显,所以不是很常见。主要还是用做优先级队列会比较合适。
1、构造函数
—-默认构造,返回一个空链表
—-两个参数,一个为正整型n,一个位对应存储结构x,初始化n个节点,所有节点值位x
—-两个参数都为对应结构的迭代子。创建一个新链表,内容为两个迭代子之间的数据
—-拷贝构造
—-move语义构造
—-列表化参数构造
例子:
// forward_list constructors
#include <iostream>
#include <forward_list>
int main ()
{
// constructors used in the same order as described above:
std::forward_list<int> first; // default: empty
std::forward_list<int> second (3,77); // fill: 3 seventy-sevens
std::forward_list<int> third (second.begin(), second.end()); // range initialization
std::forward_list<int> fourth (third); // copy constructor
std::forward_list<int> fifth (std::move(fourth)); // move ctor. (fourth wasted)
std::forward_list<int> sixth = {3, 52, 25, 90}; // initializer_list constructor
std::cout << "first:" ; for (int& x: first) std::cout << " " << x; std::cout << '\n';
std::cout << "second:"; for (int& x: second) std::cout << " " << x; std::cout << '\n';
std::cout << "third:"; for (int& x: third) std::cout << " " << x; std::cout << '\n';
std::cout << "fourth:"; for (int& x: fourth) std::cout << " " << x; std::cout << '\n';
std::cout << "fifth:"; for (int& x: fifth) std::cout << " " << x; std::cout << '\n';
std::cout << "sixth:"; for (int& x: sixth) std::cout << " " << x; std::cout << '\n';
return 0;
}
结果
forward_list constructor examples:
first:
second: 77 77 77
third: 77 77 77
fourth:
fifth: 77 77 77
sixth: 3 52 25 90
2、重载=操作符,赋值的为左值,采用copy,赋值的为右值,使用移动语义
例子:
// assignment operator with forward_list
#include <iostream>
#include <forward_list>
template<class Container>
Container by_two (const Container& x) {
Container temp(x); for (auto& x:temp) x*=2; return temp;
}
int main ()
{
std::forward_list<int> first (4); // 4 ints
std::forward_list<int> second (3,5); // 3 ints with value 5
first = second; // copy assignment
second = by_two(first); // move assignment
std::cout << "first: ";
for (int& x : first) std::cout << ' ' << x;
std::cout << '\n';
std::cout << "second: ";
for (int& x : second) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
first: 5 5 5
second: 10 10 10
3、before_begin() 顾名思义,返回第一个元素前一个元素。加上c的话表示不可修改。
例子:
// forward_list::before_begin
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {20, 30, 40, 50};
mylist.insert_after ( mylist.before_begin(), 11 );
std::cout << "mylist contains:";
for ( int& x: mylist ) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 11 20 30 40 50
4、begin()、end()、cbegin()、cend()。 返回链表的第一个和最后一个元素的跌代子,常用于遍历。
例子
// forward_list::begin example
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = { 34, 77, 16, 2 };
std::cout << "mylist contains:";
for ( auto it = mylist.begin(); it != mylist.end(); ++it )
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
结果
mylist contains: 34 77 16 2
5、empty() 判断链表是否为空
例子:
// forward_list::empty
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> first;
std::forward_list<int> second = {20, 40, 80};
std::cout << "first " << (first.empty() ? "is empty" : "is not empty" ) << std::endl;
std::cout << "second " << (second.empty() ? "is empty" : "is not empty" ) << std::endl;
return 0;
}
结果
first is empty
second is not empty
6、max_size() 返回链表的长度
例子:
// forward_list::max_size
#include <iostream>
#include <sstream>
#include <forward_list>
int main ()
{
int myint;
std::string mystring;
std::forward_list<int> mylist;
std::cout << "Enter size: ";
std::getline ( std::cin, mystring );
std::stringstream ( mystring ) >> myint;
if ( myint <= mylist.max_size() ) mylist.resize(myint);
else std::cout << "That size exceeds the maximum.\n";
return 0;
}
7、front()返回链表第一个元素,可以对其赋值
例子:
// forward_list::front
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {2, 16, 77};
mylist.front() = 11;
std::cout << "mylist now contains:";
for ( int& x : mylist ) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist now contains: 11 16 77
8、assign() 给单向链表赋值,赋值方式可以如下:
—-连续几个都一样的情况下,第一个参数为个数,第二个参数为对应的值。
—-另外一个单向链表对应的2个跌代子
—-使用初始化列表赋值
例子:
// forward_list::assign
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> first;
std::forward_list<int> second;
first.assign (4,15); // 15 15 15 15
second.assign (first.begin(),first.end()); // 15 15 15 15
first.assign ( {77, 2, 16} ); // 77 2 16
std::cout << "first contains: ";
for (int& x : first) std::cout << ' ' << x;
std::cout << '\n';
std::cout << "second contains: ";
for (int& x : second) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
first contains: 77 2 16
second contains: 15 15 15 15
10、emplace_front 从单向链表首处插入一个元素。(结构型元素)
例子:
// forward_list::emplace_front
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list< std::pair<int,char> > mylist;
mylist.emplace_front(10,'a');
mylist.emplace_front(20,'b');
mylist.emplace_front(30,'c');
std::cout << "mylist contains:";
for (auto& x: mylist)
std::cout << " (" << x.first << "," << x.second << ")";
std::cout << std::endl;
return 0;
}
结果:
mylist contains: (30,c) (20,b) (10,a)
11、push_front() 从单向链表头插入元素
例子:
// forward_list::push_front
#include <iostream>
#include <forward_list>
using namespace std;
int main ()
{
forward_list<int> mylist = {77, 2, 16};
mylist.push_front (19);
mylist.push_front (34);
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 34 19 77 2 16
12、pop_front() 获取链表头的元素,并删除链表头的元素。
例子:
// forward_list::pop_front
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {10, 20, 30, 40};
std::cout << "Popping out the elements in mylist:";
while (!mylist.empty())
{
std::cout << ' ' << mylist.front();
mylist.pop_front();
}
std::cout << '\n';
return 0;
}
结果:
Popping out the elements in mylist: 10 20 30 40
13、emplace_after() 从链表结尾插入一个元素。(结构型元素)
例子:
// forward_list::emplace_after
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list< std::pair<int,char> > mylist;
auto it = mylist.before_begin();
it = mylist.emplace_after ( it, 100, 'x' );
it = mylist.emplace_after ( it, 200, 'y' );
it = mylist.emplace_after ( it, 300, 'z' );
std::cout << "mylist contains:";
for (auto& x: mylist)
std::cout << " (" << x.first << "," << x.second << ")";
std::cout << '\n';
return 0;
}
结果:
mylist contains: (100,x) (200,y) (300,z)
14、insert_after() 从链表结尾插入一个元素或者多个元素。
入参如下:
1)要插入的开始的跌代子,
2)如果只有两个入参,为要插入的元素,可以是一个元素,也可以是初始化列表。
3)如果有三个如此,则三个入参都是跌代子,从第一个跌代子后面插入从第二个跌代子开始到第三个跌代子之间的元素。
例子:
// forward_list::insert_after
#include <iostream>
#include <array>
#include <forward_list>
int main ()
{
std::array<int,3> myarray = { 11, 22, 33 };
std::forward_list<int> mylist;
std::forward_list<int>::iterator it;
it = mylist.insert_after ( mylist.before_begin(), 10 ); // 10
// ^ <- it
it = mylist.insert_after ( it, 2, 20 ); // 10 20 20
// ^
it = mylist.insert_after ( it, myarray.begin(), myarray.end() ); // 10 20 20 11 22 33
// ^
it = mylist.begin(); // ^
it = mylist.insert_after ( it, {1,2,3} ); // 10 1 2 3 20 20 11 22 33
// ^
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 10 1 2 3 20 20 11 22 33
15、erase_after()用于删除链表元素。可以是一个或者多个。
如果入参只有一个跌代子,那么删除对应跌代子后面一个元素,
如果入参为两个跌代子,那么删除从第一个跌代子开始到第二个跌代子之间的元素。
返回删除元素最后一个元素的后一个元素。
例子:
// erasing from forward_list
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {10, 20, 30, 40, 50};
// 10 20 30 40 50
auto it = mylist.begin(); // ^
it = mylist.erase_after(it); // 10 30 40 50
// ^
it = mylist.erase_after(it,mylist.end()); // 10 30
// ^
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 10 30
16、swap() 交换两个单向链表
例子:
// forward_list::swap
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> first = {10, 20, 30};
std::forward_list<int> second = {100, 200};
std::forward_list<int>::iterator it;
first.swap(second);
std::cout << "first contains:";
for (int& x: first) std::cout << ' ' << x;
std::cout << '\n';
std::cout << "second contains:";
for (int& x: second) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
first contains: 100 200
second contains: 10 20 30
17、resize() 重新定义单向链表的长度。
参数:
第一个参数为重定义链表的长度,第二个参数为如果重定义链表的长度大于当前链表长度时补充的值。
例子:
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {10, 20, 30, 40, 50};
// 10 20 30 40 50
mylist.resize(3); // 10 20 30
mylist.resize(5,100); // 10 20 30 100 100
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 10 20 30 100 100
18、clear() 清空链表
例子:
// clearing forward_list
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = { 10, 20, 30 };
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
mylist.clear();
mylist.insert_after( mylist.before_begin(), {100, 200} );
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 10 20 30
mylist contains: 100 200
19、splice_after() 拼接链表
第一个入参为拼接的位置
第二个入参为被用于拼接的链表
第三个入参如果没有,那么第二个入参整个链表都被拼接进来,如果有,为第二个入参链表中的一个跌代子。
第4个入参如果没有,则把第三个入参的跌代子拼接到第一个入参跌代子前面,第三个入参的跌代子在第二个入参对应链表中删除。如果有值,则为将第三个入参到第四个入参跌代子范围内的值拼接到第一个跌代子前面。并从第二个入参对应的链表中删除该范围内的元素。
例子:
// forward_list::splice_after
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> first = { 1, 2, 3 };
std::forward_list<int> second = { 10, 20, 30 };
auto it = first.begin(); // points to the 1
first.splice_after ( first.before_begin(), second );
// first: 10 20 30 1 2 3
// second: (empty)
// "it" still points to the 1 (now first's 4th element)
second.splice_after ( second.before_begin(), first, first.begin(), it);
// first: 10 1 2 3
// second: 20 30
first.splice_after ( first.before_begin(), second, second.begin() );
// first: 30 10 1 2 3
// second: 20
// * notice that what is moved is AFTER the iterator
std::cout << "first contains:";
for (int& x: first) std::cout << " " << x;
std::cout << std::endl;
std::cout << "second contains:";
for (int& x: second) std::cout << " " << x;
std::cout << std::endl;
return 0;
}
结果:
first contains: 30 10 1 2 3
second contains: 20
20、remove函数,删除链表中元素值位输入值的节点。
例子:
// remove from forward_list
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {10, 20, 30, 40, 30, 20, 10};
mylist.remove(20);
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 10 30 40 30 10
21、remove_if() 用元素之执行对应结果的拷贝构造函数或者输入的函数,返回结果为true的节点被删除。
例子:
// forward_list::remove_if
#include <iostream>
#include <forward_list>
// a predicate implemented as a function:
bool single_digit (const int& value) { return (value<10); }
// a predicate implemented as a class:
class is_odd_class
{
public:
bool operator() (const int& value) {return (value%2)==1; }
} is_odd_object;
int main ()
{
std::forward_list<int> mylist = {7, 80, 7, 15, 85, 52, 6};
mylist.remove_if (single_digit); // 80 15 85 52
mylist.remove_if (is_odd_object); // 80 52
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 80 52
22、unique()删除链表中相邻且相等的元素。
如果为入参为空,则使用默认的==操作运算符,入参为函数指针,调用函数指针,如果返回true,则删除,输入参数为对象,执行器==操作运算符,如果返回true则删除。
例子:
// forward_list::unique
#include <iostream>
#include <cmath>
#include <forward_list>
// a binary predicate implemented as a function:
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }
// a binary predicate implemented as a class:
class is_near_class
{
public:
bool operator() (double first, double second)
{ return (fabs(first-second)<5.0); }
} is_near_object;
int main ()
{
std::forward_list<double> mylist = { 15.2, 73.0, 3.14, 15.85, 69.5,
73.0, 3.99, 15.2, 69.2, 18.5 };
mylist.sort(); // 3.14, 3.99, 15.2, 15.2, 15.85
// 18.5, 69.2, 69.5, 73.0, 73.0
mylist.unique(); // 3.14, 3.99, 15.2, 15.85
// 18.5, 69.2, 69.5, 73.0
mylist.unique (same_integral_part); // 3.14, 15.2, 18.5, 69.2, 73.0
mylist.unique (is_near_object); // 3.14, 15.2, 69.2
std::cout << "mylist contains:";
for (double& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 3.14 15.2 69.
23、merge() 链接两个单向链表
例子:
// forward_list::merge
#include <iostream>
#include <forward_list>
#include <functional>
int main ()
{
std::forward_list<double> first = {4.2, 2.9, 3.1};
std::forward_list<double> second = {1.4, 7.7, 3.1};
std::forward_list<double> third = {6.2, 3.7, 7.1};
first.sort();
second.sort();
first.merge(second);
std::cout << "first contains:";
for (double& x: first) std::cout << " " << x;
std::cout << std::endl;
first.sort (std::greater<double>());
third.sort (std::greater<double>());
first.merge (third, std::greater<double>());
std::cout << "first contains:";
for (double& x: first) std::cout << " " << x;
std::cout << std::endl;
return 0;
}
结果:
first contains: 1.4 2.9 3.1 3.1 4.2 7.7
first contains: 7.7 7.1 6.2 4.2 3.7 3.1 3.1 2.9 1.4
24、sort() 对单向链表进行排序
例子:
// forward_list::sort
#include <iostream>
#include <forward_list>
#include <functional>
int main ()
{
std::forward_list<int> mylist = {22, 13, 5, 40, 90, 62, 31};
mylist.sort();
std::cout << "default sort (operator<):";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
mylist.sort(std::greater<int>());
std::cout << "sort with std::greater():";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
default sort (operator<): 5 13 22 31 40 62 90
sort with std::greater(): 90 62 40 31 22 13 5
25、reverse()链表反向
例子:
// reversing forward_list
#include <iostream>
#include <forward_list>
int main ()
{
std::forward_list<int> mylist = {10, 20, 30, 40};
mylist.reverse();
std::cout << "mylist contains:";
for (int& x: mylist) std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
结果:
mylist contains: 40 30 20 10