目录
1、std::list 的特点
(1)list 是 STL 中的一个容器,实现了双向链表结构。
(2)list 中的元素可以在任何位置进行插入和删除操作,不像数组那样需要移动其他元素。
(3)list 中的元素可以动态地增加和减少,不需要预先分配空间。
(4)可以高效地进行插入和删除操作,时间复杂度为 O(1)。
(5)不支持随机访问,只能通过迭代器进行顺序访问。
(6)可以实现元素的排序操作,但是排序效率不如 vector 或 deque。
2、std::list 常用的 API
1. push_front():在 list 的头部插入一个元素
2. push_back():在 list 的尾部插入一个元素。
3. pop_back():从 list 的尾部删除一个元素
4. pop_front():从 list 的头部删除一个元素。
5. clear():清空 vector 中的所有元素。
6. size():返回 list 中元素的数量。。
7. empty():返回 list 是否为空。
8. insert():在指定位置插入一个元素。
9. erase():删除指定位置的元素。
10. splice():将两个 list 合并。
11. sort():按照指定规则对 list 中的元素进行排序。
12. reverse():将 list 中的元素反转。
以上是 std::list 常用的 API,还有其他一些 API 可以根据需要使用。
3、std::list 使用的例子
(1)初始化的几种方式
std::list 是一个双向链表容器,可以通过以下方式进行初始化:
// 1. 默认初始化
std::list<int> mylist; // 默认初始化一个空的 list
// 2. 列表初始化
std::list<int> mylist = { 1, 2, 3, 4, 5 }; // 使用花括号列表初始化 list
// 3. 拷贝初始化
std::list<int> mylist1 = { 1, 2, 3, 4, 5 };
std::list<int> mylist2(mylist1); // 拷贝初始化,将 mylist1 拷贝到 mylist2 中
// 4. 范围初始化
std::vector<int> myvector = { 1, 2, 3, 4, 5 };
std::list<int> mylist(myvector.begin(), myvector.end()); // 使用迭代器范围初始化 list
注意事项:
- 如果使用列表初始化,需要使用花括号 {},而不是圆括号 ()。
- 如果使用拷贝初始化或范围初始化,需要提供一个同类型的容器作为参数。
- 初始化 list 时,需要注意元素类型的匹配和拷贝构造函数的实现。
(2)简单一个例子:
该例子演示了如何使用 std::list 存储和操作字符串元素。
#include <iostream>
#include <list>
#include <string>
int main()
{
std::list<std::string> mylist;
// 添加元素到列表中
mylist.push_back("one");
mylist.push_back("two");
mylist.push_back("three");
mylist.push_back("four");
// 使用迭代器遍历列表中的元素
std::list<std::string>::iterator it;
for (it = mylist.begin(); it != mylist.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 在列表中插入元素
it = mylist.begin();
++it;
mylist.insert(it, "five");
// 使用迭代器遍历列表中的元素
for (it = mylist.begin(); it != mylist.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 删除列表中的元素
it = mylist.begin();
++it;
mylist.erase(it);
// 使用迭代器遍历列表中的元素
for (it = mylist.begin(); it != mylist.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
4、std::list 一些坑
(1)迭代器失效问题
std::list 的迭代器是不会因为插入或删除元素而失效的,因为它采用的是链表的数据结构,插入和删除操作只需要改变节点的指针,不会影响其他节点的位置。
但是需要注意的是,如果是使用迭代器指向的节点来删除元素,那么在删除后这个迭代器就会失效,因为它指向的节点已经被删除了。此时需要使用 erase() 函数返回的新的迭代器来继续遍历。
(2)排序问题
std::list 的 sort() 函数默认使用的是 operator< 来进行排序,如果需要按照其他方式排序,需要自定义一个比较函数并在 sort() 函数中传入。
需要注意的是,如果比较函数不满足严格弱序关系,那么排序的结果是不确定的。
(3)访问越界问题
std::list 的元素并不是连续存储的,因此不能像 vector 一样使用下标访问元素。如果需要访问某个元素,需要使用迭代器来遍历整个列表。
需要注意的是,访问不存在的元素会导致程序崩溃,因此需要在访问前进行判断。
(4)插入问题
std::list 的 insert() 函数在插入元素时,会在指定位置前插入一个新的元素。如果插入的位置是迭代器 end(),那么新元素会被插入到列表末尾。
需要注意的是,如果插入的元素是一个指针或引用,那么在插入后不能修改这个元素的值,否则会影响列表中其他节点的值。如果需要修改元素的值,需要先将其拷贝到一个新的变量中,再进行修改。