目录
容器之链表list
容器list相比于容器vector的优缺点
存储内存连续性不同
List容器存储空间不连续,不可以联系的访问数组的元素,但是vector存储空间是连续分布的,可以连续的通过下标访问数组元素。
代码示例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
vector<int> VectorArray;
VectorArray = { 6,7,8,9,10 };
}
运行结果
遍历数组的方式不同
(a)就相当于vector容器,每个元素在内存空间中都是连续分布的,可以用下标进行访问,当遍历数组时,可以用遍历数组下标的方式(VectorArray[i])进行数组元素的遍历;
(b)就相当于list容器,元素在内存中的分布可能不连续,而且元素的遍历只能通过前一个元素来访问,说白了“就相当于前一个元素中存储着该元素的访问地址,只有知道了地址才可以访问到这个元素的内容”。
由此可见,对于遍历速度来说,vector容器要快于list容器。
插入/擦去元素的效率不同
由于list容器的元素访问地址存储在前一个元素中,即元素元素之间只有通过地址才可以相互联系,从中间插入/删除元素只需改变一下地址存储的位置即可,因此这种list容器在插入/擦除元素时效率要高于vector容器。
Vector容器向元素中插入元素时,需将插入点以后的元素向后移,并且要在内存中找到有足够存储空间的存储区域来存储这个连续的动态数组,光看“数组的移动&合适内存区的查找”就知道vector容器在元素插入/擦除的效率上要慢于list容器。
迭代器本质不同
list的迭代器是双向迭代器(只能++ --,没有偏移功能)而不是像vector那样的随机迭代器(和指针几乎一样的所有功能)。在list容器中,是以链表的形式将数据串到一起的,因此不支持+n(n>1)运算。 支持++或者+n操作的有vector 和 dqueue。
容器list的相关操作
插入元素
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
list<int>::iterator ListIterator = ListArray.begin();
// list<int>::iterator ListIterator = ListArray.begin()+2是错误的,因为只有通过起始元素才可以遍历到后面的元素
ListIterator++;
ListArray.insert(ListIterator , 3, 0);
int array[]={3,4,5};
ListArray.insert(ListIterator,array,array+sizeof(array)/sizeof(int));
// 从中间插入“array”这个数组
vector<int> VectorArray;
VectorArray = { 6,7,8,9,10 };
}
一定要注意:不可以直接在任意位置插入元素,只能先从头遍历迭代器(就是相当于数组的指针要从首地址开始),用for循环逐步+1,直到要插入地方的地址。
Insert函数原型 |
list.insert(pos,elem); //在 pos 位置插入一个 elem 元素的拷贝,返回新数据的位置 |
list.insert(pos,n,elem); //在 pos 位置插入 n 个 elem 数据,无返回值 |
list.insert(pos,beg,end); //在 pos 位置插入[beg,end)区间的数据,无返回值 |
list.push_back(elem); //在容器尾部加入一个元素,也可以用emplace_back(elem),功能一样 |
list.pop_back(); //删除容器中最后一个元素 |
list.push_front(elem); //在容器开头插入一个元素 |
list.pop_front(); //从容器开头移除第一个元素 |
注: emplace_back() 和 push_back() 的区别,就在于底层实现的机制不同。push_back() 向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
擦去元素
Erase函数的用法
作用
在内存区内擦除某个位置/或某一段的元素
代码示例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
list<int>::iterator ListIterator = ListArray.begin();
// list<int>::iterator ListIterator = ListArray.begin()+2随机访问元素的做法是错误的,因为只有通过起始元素才可以遍历到后面的元素
ListIterator++; // 只能进行自加1,这是由于它本身的性质决定的
ListArray.insert(ListIterator , 3, 0);
ListIterator = ListArray.begin();
ListArray.erase(ListIterator);
}
Remove&clear函数
作用
在list容器中删除与i相同的值
代码示例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
list<int>::iterator ListIterator = ListArray.begin();
// list<int>::iterator ListIterator = ListArray.begin()+2是错误的,因为只有通过起始元素才可以遍历到后面的元素
ListIterator++;
ListArray.insert(ListIterator , 3, 0);
ListIterator = ListArray.begin();
ListArray.erase(ListIterator);
ListArray, remove(0); // 在list容器中删除与0相同的元素
ListArray.clear(); // 移除数组中所有元素
ListArray.empty(); // 查看链表容器是否为空
}
擦除函数原型 |
list.clear(); //移除容器的所有数据 |
list.erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置 |
list.erase(pos); //删除 pos 位置的数据,返回下一个数据的位置 |
lst.remove(elem); //删除容器中所有与 elem 值匹配的元素 |
倒序排列函数reverse
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
list<int>::iterator ListIterator = ListArray.begin();
// list<int>::iterator ListIterator = ListArray.begin()+2是错误的,因为只有通过起始元素才可以遍历到后面的元素
ListIterator++;
ListArray.insert(ListIterator , 3, 0);
ListIterator = ListArray.begin();
ListArray.erase(ListIterator);
ListArray, remove(0); // 在list容器中删除与0相同的元素
ListArray.reverse(); // 倒序排列
ListArray.clear(); // 移除数组中所有元素
ListArray.empty(); // 查看链表容器是否为空
}
拷贝函数assign
代码示例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
list<int>::iterator ListIterator = ListArray.begin();
// list<int>::iterator ListIterator = ListArray.begin()+2是错误的,因为只有通过起始元素才可以遍历到后面的元素
ListIterator++;
ListArray.insert(ListIterator , 3, 0);
ListIterator = ListArray.begin();
ListArray.erase(ListIterator);
ListArray, remove(0); // 在list容器中删除与0相同的元素
ListArray.reverse(); // 倒序排列
ListArray.clear(); // 移除数组中所有元素
ListArray.empty(); // 查看链表容器是否为空
int Array[] = { 1,2,3 };
ListArray.assign(Array, Array + sizeof(Array) / sizeof(int)); // 将Array数组内的元素拷贝至list容器中
}
输出结果
赋值函数模型 |
list.assign(beg,end); //将[beg,end)区间中的数据拷贝赋值给本身。注意该区间是 左闭右开的区间 |
list.assign(n,elem); //将 n 个 elem 拷贝赋值给本身 |
list.swap(lst); // 将 lst 与本身的元素互换 |
内存空间改变函数
代码示例
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
list<int> ListArray;
ListArray = { 1,2,3,4,5 };
list<int>::iterator ListIterator = ListArray.begin();
// list<int>::iterator ListIterator = ListArray.begin()+2是错误的,因为只有通过起始元素才可以遍历到后面的元素
ListIterator++;
ListArray.insert(ListIterator , 3, 0);
ListIterator = ListArray.begin();
ListArray.erase(ListIterator);
ListArray, remove(0); // 在list容器中删除与0相同的元素
ListArray.reverse(); // 倒序排列
ListArray.clear(); // 移除数组中所有元素
ListArray.empty(); // 查看链表容器是否为空
int Array[] = { 1,2,3 };
ListArray.assign(Array, Array + sizeof(Array) / sizeof(int)); // 将Array数组内的元素拷贝至list容器中
ListArray.resize(2, 0); // 重新分配list容器内存空间,将内存长度限制为2个元素,多余元素删去,如果不够2个元素,补0
}
输出结果
函数原型 |
list.resize(num); //重新指定容器的长度为 num,若容器变长,则以默认值填充新 位置。如果容器变短,则末尾超出容器长度的元素被删除 |
list.resize(num,elem); //重新指定容器的长度为 num,若容器变长,则以 elem 值填 充新位置。如果容器变短,则末尾超出容器长度的元素被删除 |
list.size(); //返回容器中元素的个数 |
vector与list相互赋值注意事项
vector->list:
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
vector<int> VectorArray{ 1,2,3,4,5 };
list<int> ListArray;
ListArray.assign(VectorArray.begin(), VectorArray.end()); // 不同类型的用迭代器&assign函数初始化
list<int> ListArray2(ListArray.begin(), ListArray.end()); // 同类型可用构造函数直接初始化
}
list->vector:
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int main()
{
vector<int> VectorArray{ 1,2,3,4,5 };
list<int> ListArray;
ListArray.assign(VectorArray.begin(), VectorArray.end()); // 不同类型的用迭代器&assign函数初始化
list<int> ListArray2(ListArray.begin(), ListArray.end()); // 同类型可用构造函数直接初始化
vector<int> VectorArray2;
VectorArray2.assign(ListArray.begin(), ListArray.end()); // 不同类型的容器均用assign&迭代器进行相互赋值
}