C++入门
C++类和对象(上)
C++类和对象(中)
C++类和对象(下)
C/C++内存管理
C++string类
C++vector类
文章目录
- 系列文章目录
- 一、list是什么?
- 二、list的使用
- 1. list的构造
- 2.list iterator的使用
- 3.list modifiers
- 三、list迭代器问题
一、list是什么?
- list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素与后一个元素。
- list与forward_list非常相似,forward_list是单链表,只能单向迭代。
- 与其他序列式容器相比(vector,array,deque),list通常在任意位置进行插入和移除元素的效率要更好。
- 与其他序列式容器相比,list和forward_list的最大缺陷就是不支持随机访问,同时list还需要一些额外的空间,以保存每个结点的相关信息。
构造函数 | 接口说明 |
---|---|
list() | 构造空的list |
lsit(size_type n, const value_type& val = value_type()) | 构造一个有n个val元素的list |
list(const list& x) | 拷贝构造函数 |
list(InputIterator first, InputIterator last) | 用迭代器区间构造list |
void test()
{
//空list
list<int> l1;
//包含10个整型1的list
list<int> l2(10, 1);
//用l2构造l3
list<int> l3(l2);
int arr[] = { 6,2,7,9 };
//用迭代器区间构造
list<int> l4(arr, arr + 4);
}
2.list iterator的使用
函数声明 | 接口说明 |
---|---|
begin + end | 返回第一个元素的迭代器 + 返回最后一个元素下一个位置的迭代器 |
rbegin + rend | 返回倒数第一个元素的迭代器 + 返回倒数最后一个元素下一个位置的迭代器 |
我们就把其当成一个带头结点的链表,begin()就是第一个元素的位置,end()就是头结点的位置。反之,rbegin()就是最后一个元素位置,rend()就是头结点的位置。
注意:
- begin()和end()为正向迭代器,对迭代器执行++ *** 作,迭代器向后移动。
- rbegin()和rend()为反向迭代器,对迭代器执行++ *** 作,迭代器向前移动。
void test2()
{
//空list
list<int> l1;
//包含10个整型1的list
list<int> l2(10, 1);
//用l2构造l3
list<int> l3(l2);
int arr[] = { 6,2,7,9 };
//用迭代器区间构造
list<int> l4(arr, arr + 4);
//正向遍历
list<int>::iterator it = l4.begin();
while (it != l4.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//反向遍历
list<int>::reverse_iterator rit = l4.rbegin();
while (rit != l4.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
3.list modifiers
函数声明 | 接口说明 |
---|---|
push_front | 在list首元素前插入元素 |
pop_front | 删除list中第一个元素 |
push_back | 在list尾部插入元素 |
pop_back | 删除list最后一个元素 |
insert | 在指定位置插入元素 |
erase | 在指定位置删除元素 |
swap | 交换两个list中元素 |
clear | 清空list中有效元素 |
void test3()
{
int arr[] = { 1,5,2,7,8,3,9,6 };
list<int> l1(arr, arr + sizeof(arr) / sizeof(arr[0]));
//在list尾部插入4,在头部插入4
l1.push_back(4);
l1.push_front(4);
PrintContainer(l1);
//删除第一个结点和最后一个结点
l1.pop_back();
l1.pop_front();
PrintContainer(l1);
//获取链表中第二个结点
auto pos = ++l1.begin();
//在pos为之前插入10
l1.insert(pos, 10);
PrintContainer(l1);
//在pos为之前插入3个0
l1.insert(pos, 3, 0);
PrintContainer(l1);
//删除pos位置上的元素
l1.erase(pos);
PrintContainer(l1);
//删除迭代器范围内元素
l1.erase(l1.begin(), l1.end());
PrintContainer(l1);
list<int> l2(arr, arr + sizeof(arr) / sizeof(arr[0]));
list<int> l3(3, 1);
PrintContainer(l2);
PrintContainer(l3);
//交换l2,l3元素
l2.swap(l3);
PrintContainer(l2);
PrintContainer(l3);
//将l2中元素清空
l2.clear();
PrintContainer(l2);
PrintContainer(l3);
}
三、list迭代器问题
在list中,迭代器失效即迭代器所指向的结点无效。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入是不会导致list的迭代器失效的,只有在删除的时候才会失效。并且失效的只是指向被删除结点的迭代器,其他的迭代器是不会受影响的。
void test4()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
list<int> l1(arr, arr + sizeof(arr) / sizeof(arr[0]));
//找到list中3这个位置的迭代器
list<int>::iterator pos = find(l1.begin(), l1.end(), 3);
cout << *pos << endl;
//删除这个迭代器所指向的元素,再打印
l1.erase(pos);
cout << *pos << endl;
}
让我们来看一下结果:
这里d出了一个断言错误,因为删除这个元素后迭代器已经失效了,我们不能再去使用一个已经失效了的迭代器。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)