1. list是序列容器,允许在序列中的任何位置执行固定O(1)时间的插入和删除操作,并在两个方向上进行迭代。
  2. list容器使用双链表实现;双链表将每个元素存储在不同的存储(内存)位置。每个节点通过next,prev指针链接成顺序表。
  3. list 与其他基本标准序列容器(array、vector和deque)相比,list 通常在容器内的任何位置插入、提取和移动元素(已经获得迭代器的情况下时间渐进复杂度O(1)) 。
  4. list 与其他序列容器(vector,array, deque)相比,list和forward _list(单链表实现)的主要缺点是它们不能通过位置直接访问元素;例如,要访问列表中的第六个元素,必须从已知位置〈如开始或结束)迭代到该位置,需要线性时间开销。
  5. 存储密度低,list要使用一些额外的内存空间(next,prev)来保持与每个元素相关联(前后序的线性)的链接信息,从而导致存储小元素类型(int, short, char)的列表的存储密度低。
int main()
{
	list<int> list1 = { 12,23,34,45,56 };
	list<int>::iterator it = list1.begin();
	it + = 4;//it不可以跳着加
// 只能 ++it,it++ ,对自己设计的类型,及可能使用++it,因为效率更快。it++会产生副本
 std::vector<int> vec
 std:: vector<int>::iterator vec1 = vec.begin()
 vec1 = vec1+5;// 完全可以,随机迭代器 
}

初始化:

int main()
{
	list<int> list1;
	//构造10个结点,并初始化为20
	list<int> list2(10, 20);
	//构造10个默认结点
	list<int> list3(10);
	// 利用别的list的已知范围来初始化
	list<int> list4(list3.begin(),list3.end());
	list<int> list5(list4);
	list<int> list5(std::list4)
  std::vector<int> vec = {1,2,3,4,5};
  list<int> list4(vec.begin(),vec.end());//新版本STL适用
	// 初始化列表方案
	list<int> list6({ 12, 23, 34 });
	list<int> list7 = { 12,23,34 };
	list<int> list8 = { 12,23,34 };
     //利用已存在的list来直接赋值
	list<int> list9 = list6;

	return 0;
}

元素访问:

不能使用下标访问和at()访问。(因为物理地址是不连续的)

int main(void) {
	list<int> ilist1{ 12,23,34,45,56 };
	list<int>::iterator it = ilist1.begin();
	cout << *it << endl;
	for (auto& x : ilist1)
	{
		cout << x << endl;
	}
	return 0;
}

迭代器失效问题:

插入数据不会出现迭代器失效问题。

  1. list和vector在插入元素的时候,是完全不同的两种情况。
    vector在插入一个元素的时候,如果容量不足,会重新申请一段空间,然后将原空间中的值拷贝到新的空间。原空间会被释放
  2. 而vector的迭代器也就失效了。
    而list,是按照结点申请,只需要把新结点插入到链表中,原始的数据并没有重新申请空间。所以不存在迭代器失效问题。
int main(void) {
	list<int> ilist1{ 12,23,34,45,56 };

	list<int>::iterator it = ilist1.begin();
	cout << *it << endl;

	ilist1.push_front(10);//可以头插
	cout << *it << endl;

	return 0;
}

删除数据,会导致迭代器失效。

因为删除数据,会导致当前节点被释放,因此指向当前结点的迭代器会失效。

int main(void) {
	list<int> ilist1{ 12,23,34,45,56 };

	list<int>::iterator it = ilist1.begin();
	cout << *it << endl;

	ilist1.pop_front();
	cout << *it << endl;
	return 0;
}

删除结点前:

java中vector和list的区别 vector list的区别与联系_迭代器失效

删除结点后:

java中vector和list的区别 vector list的区别与联系_结点_02

解决办法:

使用erase,将迭代器传入,删除当前对象,返回下一个结点的地址,让迭代器指向要删除结点的下一个位置。
但是一直删除,最终也会失效。

int main(void) {
	list<int> ilist1{ 12,23,34,45,56 };

	list<int>::iterator it = ilist1.begin();
	cout << *it << endl;

	it = ilist1.erase(it);
	cout << *it << endl;

	return 0;
}

删除前:

java中vector和list的区别 vector list的区别与联系_c++_03

删除后:

java中vector和list的区别 vector list的区别与联系_迭代器失效_04

删除重复元素:

  1. 必需先排序
  2. 才能删除重复结点
int main()
{
	list<int> list1 = { 2,4,7,3,9,7,5,3,1,4,6,8 };
	for (auto& x : list1)
	{
		cout << x << " ";
	}
	cout << endl;
	//必需先排序
	list1.sort();
	//才能删除重复结点
	list1.unique();
	for (auto& x : list1)
	{
		cout << x << " ";
	}
	
}

java中vector和list的区别 vector list的区别与联系_c++_05


删除指定元素

list1.remove(23);

vector和list的区别

底层实现不同

vector:连续存储的容器,是一个动态数组,在堆区上分配空间。
list:动态双向链表,靠各个结点地址连接起来,在堆区分配空间。

空间利用率

vector:连续空间,不易造成内存碎片。空间利用率高
list:结点不连续,易造成内存碎片,小元素使结点密度低。空间利用率低。

查询元素

vector:由于是连续空间,所以可以通过 iterator, operator[],find()来查询,时间复杂度为O(n),还可通过二分查询binary_serach(),时间复杂度O(log2n)。
list:空间不连续,只能通过iterator, find()来查询,时间复杂度O(n)。

插入和删除

vector:
在末尾插入:1. 容量足够,push_back()时间复杂度为O(1).
2.容量不足时,push_back()时间复杂度为O(n); 因为需要重新申请空间,再把原有数据拷贝过去。
在中间插入:1.容量够时,需要插入后需要将后面数据后移。2.容量不够时,重新申请空间,再拷贝之前数据。
insert(it, val):O(n);
删除:尾删(pop_back()),O(1);其他地方O(n);
erase(it): O(n);
list:
插入:需要申请内存,时间复杂度O(1),push_back(),push_front(),insert(it, val);
删除:需要释放内存,时间复杂度O(1),pop_back(), pop_front()
erase(it):O(n);

迭代器

vector:
随即迭代器,迭代器检查越界。支持 ++, – , +, += , > , < , == , !=
list:
双向迭代器,迭代器检查越界。支持 ++, --, ==, !=。

迭代器失效

vector:
插入和删除都会导致迭代器失效
list:
插入元素不会导致迭代器失效;删除元素使当前迭代器失效,不影响其他迭代器。

总结

在平时使用时,不能谈论某个容器的优缺点,因为每种容器都有它适合的场景,只能说哪种容器在哪种场合更实用。

vector底层实现是数组; list是双向链表。
vector支持随机访问,list不支持。
vector是顺序内存,list不是。
vector在中间节点进行插入删除会导致内存拷贝,list不会。
vector一次性分配好内存,不够时才进行2倍扩容(或1.5倍);list每次插入新节点都会进行内存申请。
vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。
什么时候该用vector? 什么时候该用list?

如果需要高效的随机存取,而不在乎插入和删除的效率(很少使用插入和删除操作)。选用vector。
如果需要大量的插入和删除的操作,随机存取很少使用。选用list.