ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C++ | STL 浅谈list容器

2020-03-16 20:05:30  阅读:298  来源: 互联网

标签:std 容器 const 浅谈 iterator STL list lst1


目录

一.简述list容器

二.list容器创建方式

三.list容器的插入和删除操作

四.关于list容器迭代器的使用方法


一.简述list容器

 list是双向链表容器,也就是说它的底层是一个双向循环链表。所需头文件#include<list>

因为list是双向链表容器,所以它的逻辑地址连续,但是它的物理地址并不连续,因此我们不能使用指针的直接跳转来访问该双向链表的某一元素。例如在上图中,指针arr指向某个双向链表的头结点,当我们想要访问这个双向链表的第二个元素时,就不能以*(arr+2)这种方式来访问,这也就意味着后续我们使用迭代器对list容器进行访问的时候,不能使用 iterator+i (iterator代表迭代器,i=0,1,2,3.....n)这种方式来访问。

二.list容器创建方式

#include<iostream>
#include<vector>
#include<list>
#include<functional>

int main()
{
	std::list<int> lst1;
	std::list<int> lst2(10);//count
	std::list<int> lst3(10, 20);//count, value
	std::list<int> lst4(lst3.begin(), lst3.end());

	return 0;
}

在构造list容器lst1时,调用的是list类中默认的构造函数,(所有的容器中都有默认的构造函数),且构造的同时没有做任何事情。

在构造list容器lst2时,我们显式的给定了这个容器的初始大小10,并且将这10个大小的数据置为0。

在构造list容器lst3时,我们显式的给定了这个容器的初始大小10,且显式的将这10个大小的数据置为20。即我们给lst3中插入了10个值为20的数据。

在构造list容器lst4时,我们传入的参数是一个迭代器区间,即将lst3的开始和末尾的后一个位置传入,也就是将lst3中的数据插入到lst4中。

三.list容器的插入和删除操作

#include<iostream>
#include<vector>
#include<list>
#include<functional>

template<typename Iterator>
void Show(Iterator first, Iterator last)
{
	for (first; first != last; first++)
	{
		std::cout << *first << " ";
	}
	std::cout << std::endl;
}

int main()
{
	std::list<int> lst1;


	for (int i = 0; i < 3; i++)
	{
		lst1.push_back(i + 1);
	}// 1 2 3
	for (int i = 0; i < 3; i++)//3 2 1 1 2 3
	{
		lst1.push_front(i + 1);
	}
	Show(lst1.begin(), lst1.end());

	lst1.insert(++lst1.begin(), 6);
	Show(lst1.begin(), lst1.end());

	lst1.pop_front();
	Show(lst1.begin(), lst1.end());

	lst1.pop_back();
	Show(lst1.begin(), lst1.end());

	lst1.erase(++lst1.begin(), --lst1.end());
	Show(lst1.begin(), lst1.end());

	return 0;
}

 

push_back 即尾插,在链表的尾部插入元素,时间复杂度O(1)。

push_front 即头插,在链表的头部插入元素,时间复杂度O(1)。

insert 即按位置来插入元素,insert函数有以下五个重载,时间复杂度O(1)

  1. iterator std::list<_Ty, _Alloc>::insert<_Iter, >(const const_iterator _Where, _Iter _First, _Iter _Last),按位置(Where)插入一个区间(Iter_First~Iter_Last)里面的元素,这个区间代表的是一个迭代器区间。
  2. iterator std::list<_Ty, _Alloc>::insert(const_iterator _Where, size_type _Count, const _Ty & _Val),在Where这个位置插入Count个值为Val的元素。
  3. iterator std::list<_Ty, _Alloc>::insert(const_iterator _Where, const _Ty & _Val),在Where这个位置插入一个值为Val的元素,且这个值被const锁修饰,所以值不能被修改。
  4. iterator std::list<_Ty, _Alloc>::insert(const_iterator _Where, _Ty && _Val),在Where这个位置插入一个值为Val的元素,但这个值没有被const锁修饰。
  5. iterator std::list<_Ty, _Alloc>::insert(const_iterator _Where, initializer_list<_Ty> _Ilist),使用初始化列表在Where位置插入新的元素,例如
     lst1.insert(lst1.begin(),{1,3,4});

     

pop_front 即头删,删除链表的首元素,时间复杂度O(1)。

pop_back 即尾删,删除链表的尾部元素,时间复杂度O(1)。

erase 即按位置来删除,erase函数有以下两个重载,时间复杂度O(1)

  1. iterator erase(const const_iterator _First, const const_iterator _Last),删除某个迭代器区间的所有元素。
  2.  iterator erase(const const_iterator _Where),删除Where这个位置的元素。

访问,即Show()函数的时间复杂度为O(n)。

所以list容器的优点是“任意位置快速的插入或删除”,缺点是“访问的效率较低”。

四.关于list容器迭代器的使用方法

#include<iostream>
#include<vector>
#include<list>
#include<functional>

int main()
{
	int arr[] = { 1, 3, 214, 23, 5, 3 };
	int len = sizeof(arr) / sizeof(arr[0]);

	std::vector<int> vec(arr, arr + len);//内存连续   随机访问迭代器
	std::list<int> lst(vec.begin(), vec.end());//内存不连续	双向迭代器  ++ --	

	std::cout << vec[2] << std::endl;
	//std::cout << lst[1] << std::endl;

	std::vector<int>::iterator vit = vec.begin() + 2;
	std::cout << *vit << std::endl;

	//std::list<int>::iterator  lit = lst.begin() + 2;
        //std::cout << *lit << std::endl;

	return 0;
}

 

我们知道vector容器的底层是一个数组,它的逻辑和物理地址都是连续的,因此我们可以使用指针加上偏移来访问数据,而list容器的物理地址地址是不连续的,因此我们不能通过指针加上偏移来访问数据。我们把vector容器中的迭代器称为 随机访问迭代器,而list容器中的迭代器称为 双向迭代器。

通俗的讲,双向迭代器不能进行 +i 或 -i 的操作,如果要遍历容器,那么它只能进行++ 或 --操作。(i=1,2,3....n)

而随机访问迭代器,既能进行 +i 或 -i 的操作,也能进行++ 或 -- 操作。(i=1,2,3....n)

标签:std,容器,const,浅谈,iterator,STL,list,lst1
来源: https://blog.csdn.net/ThinPikachu/article/details/104906387

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有