C++ STL list类

本文深入探讨了C++标准模板库中的List容器,解析了其内部实现为带头节点的双向循环链表,对比了与其他序列容器如vector和deque在插入和删除操作上的效率优势。详细介绍了List的构造函数、迭代器的使用及其封装过程,以及如何检测list是否为空和获取元素等关键操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

list类

概念:

1.list底层是**带头节点双向循环链表**。
2. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代已让其更简单高效。
3. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。 
4.  list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

常用方法、接口:

构造函数:
构造空的list:

list<int> L;

构造list中包含n个值为val的元素:

list<int> L(size_t n,const T& val);

区间构造list:

list<int>(iterator first,iterator last);//这里的迭代器不是原生态迭代器,需要进行将节点类型的指针重新封装。后面会说到。

拷贝构造:

list<int> L1(10,5);
list<int> L2(L1);

list迭代器的使用:
begin()&end();rbegin()&rend();
注意:
1.begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动。
2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动。
3. list迭代器不是原生态的指针,因为++操作不能指向下一个节点,后面会详细说明。

补充:
list中的迭代器失效只有一种场景:迭代器指向的节点不存在。
在这里插入图片描述
在list中因为迭代器不是原生态指针,不能直接++操作取到下一个节点,所以这里我们需要将节点类型的指针封装成迭代器

list迭代器:将节点类型的指针封装:
步骤:
1.迭代器的构造

    list_iterator(Node* pCur)
		: _pCur(pCur)
	{}

2.将迭代器的对象按照指针的方式应用(例如:* ->)

T& operator*()
	{
		return _pCur->_data;
	}

T* operator->()
	{
		return &(_pCur->_data);
	}

3.让迭代器可以移动(++ --)

Self& operator++()//前置++
	{
		_pCur = _pCur->_pNext;
		return *this;
	}
 Self operator++(int)//后置++
	{
		Self temp(*this);
		_pCur = _pCur->_pNext;
		return temp;
	}
	Self& operator--()//前置--
	{
		_pCur = _pCur->_pPre;
		return *this;
	}

	Self operator--(int)//后置--
	{
		Self temp(*this);
		_pCur = _pCur->_pPre;
		return temp;
	}

注意:自定义类型作为返回值时,尽量返回引用,这样效率高,如果按值得方式返回,还需要创建一个临时对象。(但是需注意若要用引用返回返回值,返回值生命周期必须比此函数长)
4.迭代器之间可以进行比较(== !=)

bool operator!=(const Self& s)
	{
		return _pCur != s._pCur;
	}

	bool operator==(const Self& s)
	{
		return _pCur == s._pCur;
	}

补充:
如何给一个类定义迭代器:
1.分析该类的迭代器是原生态指针还是需要对指针进行重新封装。(取决于当前的数据类型:vector:原生态指针, list:需要对原生态指针进行封装)
2.结合该种数据结构,定义迭代器类
3.将迭代器与类结合:在容器类中–》typedef 迭代器类型 iterator(这样写为了统一,方便应用)。
4.容器应该提供:begin()和end()。

list 容量
检测list是否为空,是返回true,否返回false。

list<int> L(10, 5);
if (L.empty())
	cout << "空" << endl;
else
	cout << "非空" << endl;

在这里插入图片描述

返回list中的节点个数

list<int> L(10, 5);
cout << L.size() << endl;

在这里插入图片描述

元素访问
访问链表中第一个节点中值

vector<int> v{ 1, 2, 3 };
list<int> L(v.begin(),v.end());
cout << L.front() << endl;

在这里插入图片描述
访问链表中最后一个节点中的值

vector<int> v{ 1, 2, 3 };
list<int> L(v.begin(),v.end());
cout << L.back() << endl;

在这里插入图片描述

总结:

vector和list的区别:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值