std::list是双向链表,是一个允许在序列中任何一处位置以常量耗时插入或删除元素且可以双向迭代的顺序容器。其所在的头文件是#include。其初始化赋值方法与vetor一样。不再进行解释。
下面介绍一些在List中常用的函数:(假如这里我们定义了一个链表:list queList)
1)queList.push_front()就代表着在链表的头部插入元素;同理,queList.push_back()就代表着在链表的尾部插入元素。queList.pop_front()就是弹出链表的头部元素;queList.pop_back()就是弹出链表的尾部元素。
2)queList.begin()指向链表的头。end()成员函数返回指向末尾位置的迭代器。**这个“末尾位置”指的是最后一个元素再往后一位,也就是说end()所指的位置不包含有效元素,它相当于一个虚设的节点。**这样设计是为了满足C++标准库表示区间时左闭右开的惯例。
3)insert(it, val)成员函数用于在链表中插入元素。
typedef list<int>::iterator Iter;
Iter it=queList.end();
it为该链表的一个迭代器,val为待插入的值,插入后val位于it所指位置的前一位。返回值为一个迭代器,表示val插入到了哪个位置。
4)remove(it)成员函数用于删除某个迭代器所指的节点。注意在删除之后it就失效了,除非给it重新赋值,否则对它的任何操作都会导致错误!
eg:
queList.remove(it);
int x = *it + 10; //ERROR!
5)List的反向遍历
由于list容器的迭代器具有"–"操作,因此也定义了反向迭代器。用反向迭代器来进行链表的遍历。
list<int>::reverse_iterator ri,rend;
rend=l.rend();//rend()返回一个逆序迭代器,它指向容器c的最后一个元素
cout << "反向遍历:";
for(ri=l.rbegin();ri!=rend;ri++)//rbegin()返回一个逆序迭代器,它指向容器c的最后一个元素
{
cout << *ri << " ";
}
6)List的归并与排序
void splice(iterator position,list& x) 将x的链表归并到当前list链表的position之前,list对象x将被清空
void splice(iterator position,list&,iterator i) 将一个list的迭代器i值所指的元素,归并到当前list链表中,并将被归并的元素从原链表中删除
void merge(list& x) 将list对象x的链表归并到当前list链表中,并清空x的链表。从merge函数的源码可知,只有当前的list链表和x均预先按元素的"<“关系排好序,merge函数才有意义,归并后的链表也是按”<"关系排列。
7)size()返回链表内元素的个数,empty()判断链表是否为空,remove(val)用于移除所有值为val的节点
附题目
#include<iostream>
#include<list>
using namespace std;
using Iter=list<int>::iterator;
const int maxn=1e5+10;
Iter pos[maxn];
list<int >queList;
bool erased[maxn];
int n;
void build()
{
queList.push_front(1);
pos[1]=queList.begin( );
for(int i=2;i<=n;i++)
{
int k,p;
cin>>k>>p;
if(p==0)
pos[i]=queList.insert(pos[k],i);
else
{
auto nextIter=next(pos[k]);
pos[i]=queList.insert(nextIter,i);
}
}
int m;
cin>>m;
for(int x,i=1;i<=m;i++)
{
cin>>x;
if(!erased[x])
queList.erase(pos[x]);
erased[x]=true;
}
}
int main( )
{
cin>>n;
build();
for(int x:queList)
{
cout<<x<<" ";
}
cout<<endl;
return 0;
}