C++ STL——list
注:原创不易,转载请务必注明原作者和出处,感谢支持!
注:内容来自某培训课程,不一定完全正确!
一 list容器
链表list是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。(熟悉的链表的味道)
list特性总结:
(1) 采用动态存储分配,不会造成内存浪费和溢出
(2)链表执行插入和删除十分方便,修改指针即可,不需要移动大量元素
(3)链表灵活,但是空间和时间额外耗费比较大
如图所示,C++中list实际上更像是双向链表。它所支持的常用操作也在图中列出。
链表和数组有什么区别?
(1)数组必须事先定义固定长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;当数据减少时,造成内存浪费。
(2)链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入,删除数据元素。在数组中插入,删除数据项时,需要移动其它数据项。
1.1 list常用API
构造函数
list<T> lst; // 对象的默认构造形式
list(beg, end); // 将[beg, end)区间中的元素拷贝给本身
list(n, elem); // 将n个elem元素拷贝给本身
list(const list &lst); // 拷贝构造函数
插入和删除
push_back(elem); // 尾部插入元素
pop_back(); // 尾部删除元素
push_front(); // 首部插入元素
pop_front(); // 首部删除元素
insert(pos, elem); // 在pos位置插入elem元素,返回数据的位置
insert(pos, n, elem); // 在pos位置插入n个elem元素,无返回值
insert(pos, beg, end); // 在pos位置插入区间[beg, end)的元素,无返回值
clear(); // 清空容器
erase(beg, end); // 删除[beg, end)区间内的数据
erase(pos); // 删除pos位置的数据,返回下一个数据的位置
remove(elem); // 删除容器中所有与elem匹配的元素
大小操作
size(); // 返回容器中元素个数
empty(); // 判断容器是否为空
resize(num); // 重新指定容器的长度为num,若容器变长,则以默认值填充。如果容器变短,则超出容器长度元素将被删除
resize(num, elem); // 重新指定容器长度为num,elem为填充的默认值
赋值操作
assign(beg, end); // 将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem); // 将n个elem拷贝赋值给本身
// 重载等号运算符
list &operator=(const list &lst);
swap(lst); // 将lst与本身的元素互换
数据存取
front(); // 返回第一个元素
back(); // 返回最后一个元素
逆序和排序
reverse(); // 反转链表
sort(); // 排序
1.2 list应用案例
void printList(list<int> &l)
{
for (list<int>::iterator it = l.begin(); it != l.end(); ++it)
{
cout << *it << " ";
}
cout << endl;
}
// 初始化
void Test1()
{
list<int> lst1;
list<int> lst2(10, 10);
list<int> lst3(lst2.begin(), lst2.end());
list<int> lst4(lst3);
printList(lst4);
}
// 插入和删除
void Test2()
{
list<int> lst;
lst.push_back(100);
lst.push_front(200);
lst.insert(lst.begin(), 500);
lst.insert(lst.end(), -100);
list<int>::iterator pos = lst.begin();
pos++;
pos++;
// 在lst.begin() + 2的位置前插入2个10
lst.insert(pos, 2, 10);
printList(lst);
pos = lst.begin();
int arr[] = { 1, 2, 3, 4, 5 };
pos++; pos++; pos++; pos++;
lst.insert(pos, arr, arr + sizeof(arr) / sizeof(int));
printList(lst);
// 删除
lst.pop_back();
lst.pop_front();
printList(lst);
lst.remove(10);
printList(lst);
lst.erase(lst.begin(), lst.end());
if (lst.empty())
{
cout << "list is empty !" << endl;
}
}
// 赋值
void Test3()
{
list<int> l;
l.assign(10, 10);
list<int> l2;
l2 = l;
printList(l2);
}
// 从大到小排序
bool cmp(int a, int b)
{
return a > b;
}
// 逆序和排序
void Test4()
{
int arr[] = { 1, 4, 9, 5, 8, 2, 7 };
list<int> l(arr, arr + sizeof(arr) / sizeof(int));
printList(l);
l.reverse();
printList(l);
// 这里的sort()是list的成员函数不是alogrithm里的算法
l.sort(cmp);
printList(l);
}
注意:算法algorithm头文件中的sort()算法只支持可随机访问的容器,而list是不支持随机访问的,所以list自己提供了sort()成员方法。