C++ 标准库类型List

C/C++总述:Study C/C++-CSDN博客

目录

定义和初始化list对象

list中元素的访问

list的大小与容量

list的增

list的删

list的改

list的模拟实现


C++ 标准库中的 list 是一种双向链表容器,它支持快速的插入和删除操作。

list 容器中各个元素的前后顺序是靠指针来维系的,每个元素都配备了 2 个指针,分别指向它的前一个元素和后一个元素。其中第一个元素的前向指针总为 null,因为它前面没有元素;同样,尾部元素的后向指针也总为 null。

cpp 复制代码
#include <list>
using std::list;

定义和初始化list对象

  1. 创建一个没有任何元素的空 list 容器:

    cpp 复制代码
    list<int> lt;
  2. 创建一个包含 n 个元素的 list 容器:

    cpp 复制代码
    list<int> lt(10);//创建lt容器,其中包含10个元素,每个元素的值都为相应类型的默认值(int类型的默认值为0)
  3. 创建一个包含 n 个元素的 list 容器,并为每个元素指定初始值:

    cpp 复制代码
    list<int> lt(10, 5);//创建了一个包含10个元素并且值都为5个lt容器。
  4. 在已有 list 容器的情况下,通过拷贝该容器可以创建新的 list 容器:

    cpp 复制代码
    list<int> lt1(10);
    list<int> lt2(lt1);//注意:采用此方式,必须保证新旧容器存储的元素类型一致。
  5. 通过拷贝其他类型容器(或者普通数组)中指定区域内的元素,可以创建新的 list 容器:

    cpp 复制代码
    //拷贝普通数组,创建list容器
    int a[] = { 1,2,3,4,5 };
    list<int> lt1(a, a+5);
    //拷贝其它类型的容器,创建 list 容器
    vector<int, 5>ve{ 11,12,13,14,15 };
    list<int>lt(ve.begin()+2, ve.end());//拷贝ve容器中的{13,14,15}

list中元素的访问

成员函数 功能
front() 返回第一个元素的引用。
back() 返回最后一个元素的引用。
begin() 返回指向容器中第一个元素的双向迭代器。
end() 返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。
rbegin() 返回指向最后一个元素的反向双向迭代器。
rend() 返回指向第一个元素所在位置前一个位置的反向双向迭代器。
cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。

list的大小与容量

成员函数 功能
empty() 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
size() 返回当前容器实际包含的元素个数。
max_size() 返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
front() 返回第一个元素的引用。
back() 返回最后一个元素的引用。

list的增

成员函数 功能
push_front() 在容器头部插入一个元素。
push_back() 在容器尾部插入一个元素。
emplace() 在容器中的指定位置插入元素。该函数和 insert() 功能相同,但效率更高。
insert() 在容器中的指定位置插入元素。
splice() 将一个 list 容器中的元素插入到另一个容器的指定位置。

list的删

|-------------|---------------------|
| pop_front() | 删除容器头部的一个元素。 |
| pop_back() | 删除容器尾部的一个元素。 |
| erase() | 删除容器中一个或某区域内的元素。 |
| clear() | 删除容器存储的所有元素。 |
| remove(val) | 删除容器中所有等于 val 的元素。 |
| remove_if() | 删除容器中满足条件的元素。 |
| unique() | 删除容器中相邻的重复元素,只保留一个。 |

list的改

成员函数 功能
assign() 用新元素替换容器中原有内容。
swap() 交换两个容器中的元素,必须保证这两个容器中存储的元素类型是相同的。
resize() 调整容器的大小。
merge() 合并两个事先已排好序的 list 容器,并且合并之后的 list 容器依然是有序的。
sort() 通过更改容器中元素的位置,将它们进行排序。
reverse() 反转容器中元素的顺序。

list的模拟实现

cpp 复制代码
#include<string>
#include<vector>
#include<iostream>
 
using namespace std;
namespace mylist 
{
	template<class T>
    //链表的每个结点的结构
	struct list_node 
	{
		T _data;            //存放数据
		list_node<T>* _prev;//指向前一个结点的指针
		list_node<T>* _next;//指向后一个结点的指针
 
		list_node(const T& val = T())  //构造一个结点对象
			:_data(val)
			, _prev(nullptr)
			, _next(nullptr)
		{ }
	};
 
	// T T& T*
	// T cosnt T& const T*
	template<class T,class Ref,class Ptr>
	struct __list_iterator                   //list的迭代器结构
	{
		typedef list_node<T> Node;             //结点
		typedef __list_iterator<T,Ref,Ptr> _self; //_self就是一个实例化的迭代器
		Node* _node;                          //结点的指针
 
		__list_iterator(Node* node)
			:_node(node)
		{
 
		}
 
		Ref operator*()                //重载运算符* 通过*能够访问结点里面的数据
		{
			return _node->_data;
		}
        
		Ptr operator->()         //重载-> , 结构体指针访问成员可以用结构体对象->结构体成员
		{
			return &_node->_data;
		}
 
		_self& operator++()   //重载运算符前置++,返回下一个结点的迭代器
		{
			_node = _node->_next;
			return (*this);
		}
 
		_self& operator--()  //重载运算符前置--,返回前一个结点的迭代器
		{
			_node = _node->_prev;
			return (*this);
		}
 
		_self operator++(int)  //重载运算符后置++,返回当前结点的迭代器的拷贝再++
		{
			Node* tmp(_node);
			_node = _node->_next;
 
			return tmp;
		}
 
		_self operator--(int) //重载运算符前置--,返回当前一个结点迭代器的拷贝再--
		{
			Node* tmp(_node);
			_node = _node->_prev;
 
			return tmp;
		}
 
		bool operator!=(const _self& n)  //重载迭代器的比较运算符!=
		{
			return this->_node != n._node;
		}
 
		bool operator==(const _self& n)  //重载迭代器的比较运算符==
		{
			return this->_node == n._node;
		}
 
	};
 
	template<class T>
	class list
	{
		typedef list_node<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;
 
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}
			
		const_iterator end() const
		{
			return const_iterator(_head);
		}
 
		iterator begin()
		{
			return (_head->_next);
		}
 
		iterator end()
		{
			return _head;
		}
 
		void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			_size = 0;
		}
 
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
 
		}
 
		void swap(list<T>& lt)
		{
			std::swap(_head, lt._head);
			std::swap(_size, lt._size);
		}
 
		list()
		{
			empty_init();
		}
 
		//lt1(lt2)
		list(const list<T>& lt)
		{
 
			empty_init();
			for (auto e : lt)
			{
				push_back(e);
			}
		}
 
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
 
		list<int>& operator=(list<int>lt)
		{
			swap(lt);
			return *this;
		}
 
		void push_back(const T& x)
		{
			insert(end(), x);
		}
 
		void push_front(const T& x)
		{
			insert(begin(), x);
		}
 
		void pop_back(const T& x)
		{
			erase(--end());
		}
 
		void pop_front(const T& x)
		{
			erase(begin());
		}
 
		iterator insert(iterator pos, const T& x)
		{
			Node* newnode = new Node(x);
			Node* cur = pos._node;
			Node* prev = cur->_prev;
 
			prev->_next = newnode;
			newnode->_prev = prev;
 
			newnode->_next = cur;
			cur->_prev = newnode;
 
			++_size;
			return iterator(newnode);
 
		}
 
		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;
 
			delete cur;
			prev->_next = next;
			next->_prev = prev;
			--_size;
			return iterator(next);
		}
 
		size_t size()
		{
			return _size;
		}
 
	private:
		Node* _head; //list的头结点
		size_t _size;//list的大小
 
	};
}
相关推荐
swordbob2 分钟前
CAP 定理:为什么不能同时实现 C、A、P?
开发语言·后端·spring
疯狂成瘾者2 分钟前
Java 常用工具包 java.util
java·开发语言·windows
枫叶丹43 分钟前
【HarmonyOS 6.0】MDM Kit 新特性:PC/2in1设备无锁屏密码重启自动解锁能力详解
开发语言·华为·harmonyos
ZHW_AI课题组23 分钟前
Python 调用百度智能云 API 实现地址识别
开发语言·人工智能·python·机器学习·百度·数据挖掘
88号技师41 分钟前
2026年2月一区SCI-交叉传播优化算法Propagation Alongside Crossover-附Matlab免费代码
开发语言·算法·数学建模·matlab·优化算法
chase_my_dream42 分钟前
LeGO-LOAM 详细源码流程解读
c++·计算机视觉·自动驾驶
A.零点1 小时前
【2个月 C 语言从入门到精通:零基础系统教程】第十二讲:深入了解指针(五)
c语言·开发语言·网络·笔记·visual studio
飞天狗1111 小时前
零基础JavaWeb入门——第五课第一小节:九大内置对象 · 第1个:request(请求对象)
java·开发语言·前端·后端·servlet
z落落1 小时前
C#ToolStrip+StatusStrip 状态栏实时显示系统时间+NotifyIcon系统托盘
开发语言·c#
插件开发1 小时前
vs2015 cuda c++ 线程号的计算详解
开发语言·c++·算法