1. STL序列容器中的list容器
STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。
STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。
在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>
STL提供了很多种容器,每种容器都提供一组操作行为即算法接口。序列容器包括向量(vector)、双端队列(deque)、双向链表(list)。
目录
1.1 list的基本概念
链表(list),即双向链表容器,它不支持随机访问,访问链表元素要指针从链表的某一个端点开始,插入和删除操作所花费的时间是固定的,和该元素在链表中的位置无关,list在任何位置插入和删除动作都很快,不像vector只在尾端操作。
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
创建一个list对象,可以通过一些方式:
1) std::list<type> name;
2) std::list<type> name(size);
3)std::list<type> name(size,value);
4) std::list<type> name(first,last);
1.2 list的特点
a. list采用动态存储分配,不会造成内存浪费和溢出
b. list链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
c. list链表灵活,但是空间和时间额外耗费较大
1.3 list的迭代器
List容器不能像vector一样以普通指针作为迭代器,因为其节点不能保证在同一块连续的内存空间上。
List迭代器必须有能力指向list的节点,并有能力进行正确的递增、递减、取值、成员存取操作。所谓”list正确的递增,递减、取值、成员取用”是指,递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的数据值,成员取用时取的是节点的成员。
由于list是一个双向链表,迭代器必须能够具备前移、后移的能力,所以list容器提供的是Bidirectional Iterators.
List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效。这在vector是不成立的,因为vector的插入操作可能造成记忆体重新配置,导致原有的迭代器全部失效,甚至List元素的删除,也只有被删除的那个元素的迭代器失效,其他迭代器不受任何影响。
char cTemp;
list<char> charlist;
for (int i = 0; i < 5; i++)
{
cTemp = 'a' + i;
charlist.push_front(cTemp);
}
cout << "list old:" << endl;
list<char>::iterator it;
for (it = charlist.begin(); it != charlist.end(); it++)
{
cout << *it << endl;
}
1.4 list的数据结构
list容器不仅是一个双向链表,而且还是一个循环的双向链表。
1.5 list的常用API
函数 | 说明 |
assign(first,last) | 用迭代器first和last所辖范围内的元素替换链表元素,??? |
assign(num,val) | 用val的num个副本替换链表元素,??? |
back() | 返回对一个链表最后一个元素的引用 |
begin() | 返回指向链表中第一个元素的迭代器 |
insert(i,n,x) | 把x的n个副本插入到链表中由迭代器i所指明的位置 |
clear() | 删除链表中所有元素 |
empty() | 如果链表为空,则返回为true值 |
end | 返回指向链表中最后一个元素的迭代器 |
erase(i) | 删除迭代器i所指向的链表元素 |
erase(start,end) | 删除迭代器start和end所管辖范围内的链表元素 |
front() | 返回对链表第一个元素的引用 |
insert(i,start,end) | 把迭代器start和end所管辖范围内的元素插入到链表中由迭代器i所指明的位置 |
insert(i,x) | 把值x插入链表中由迭代器i所指明的位置 |
insert(i,n,x) | 把x的n个副本插入到链表中由迭代器i所指明的位置 |
max_size | 返回链表的最大容量 |
pop_back() | 删除链表最后一个元素 |
pop_front() | 删除链表第一个元素 |
push_back(x) | 把值x放在链表末尾 |
push_front(x) | 把x放到链表的开始 |
rbegin | 返回一个反向迭代器,指向链表末尾元素之后 |
rend | 返回一个反向迭代器,指向链表起始元素 |
size() | 返回链表的大小(元素的个数) |
swap(list) | 交换两个链表的内容 |
resize(n,x) | 重新设置链表大小n,新元素的值初始化为x |
reverse | 颠倒链表元素的顺序 |
insert接口的应用代码如下:
list<char>::iterator itstart = charlist.begin();
charlist.insert(++itstart,2,'A');
cout << "list old" << endl;
for (it = charlist.begin(); it != charlist.end(); it++)
{
cout << *it << endl;
}