爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      【C++】list的使用 | 模拟实现

      首页 知识中心 软件开发 文章详情页

      【C++】list的使用 | 模拟实现

      2024-05-29 08:28:31 阅读次数:44

      c++,list,链表

      一、list的使用

      前面我们在数据结构阶段讲过:【双向带头循环链表】,其实我们前面所讲过的双向带头循环链表就是基于STL中的list所实现的。双向带头循环链表的整体结构如下:
      【C++】list的使用 | 模拟实现

      对于list,我们需要注意以下几点:

      1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
      2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
      3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
      4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
      5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

      1. 构造函数

      【C++】list的使用 | 模拟实现

      int main()
      {
      	//默认构造
      	list<int> lt;
      	lt.push_back(1);
      	lt.push_back(2);
      	lt.push_back(3);
      	lt.push_back(4);
      	lt.push_back(5);
      	//拷贝构造
      	list<int> lt2(lt);
      	//迭代器区间构造
      	list<int> lt3(lt.begin(), lt.end());
      	//构造n个val
      	list<int> lt4(5, 1);
      
      	return 0;
      }
      

      2. 迭代器

      【C++】list的使用 | 模拟实现

      此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。

      【C++】list的使用 | 模拟实现

      注意:

      1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动
      2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动。

      3. 增删查改

      【C++】list的使用 | 模拟实现

      这里我们需要注意的是:由于list是一个链表,它的物理地址是不连续的,所以list不支持[]访问,list的空间是使用一个开辟一个,所以他也是不支持reserve操作的。


      4. 其他成员函数

      【C++】list的使用 | 模拟实现

      sort——链表排序

      我们知道算法库中是有一个sort函数的,但由于list中节点的空间是不连续的,所以不能使用算法库中的sort函数,所以list自己提供了一个sort函数,但是这个接口我们一般也不会使用,因为链表排序的效率实在是太低了。

      unique——链表去重

      我们在使用链表去重之前需要保证链表有序,否则就会导致去重不完全。

      remove——移除链表中的指定元素

      remove用来移除链表中的指定元素,如果元素不存在,则此接口什么都不会做。

      merge——归并两个有序链表

      这里我们需要注意的是,两个链表必须有序才能够调用这个函数来进行归并,而且归并之后,被归并的一方的元素将会消失,相当于把一方中的元素转移到了另一方中,而且,归并后的链表依然保持有序。


      二、list的模拟实现

      1. 节点的创建

      //节点的封装
      template<class T>
      struct list_node
      {
      	list_node<T>* _prev;
      	list_node<T>* _next;
      	T _val;
      	//构造函数
      	list_node(const T& val = T())
      		:_prev(nullptr)
      		,_next(nullptr)
      		,_val(val)
      	{}
      };
      

      首先,由于节点存储的数据可能是任意类型,所以我们需要将将节点定义为模板类。这里我们需要写一个给缺省值的默认构造函数,便于之后在主类中new一个新节点时直接初始化,同时将两个指针置为空,将数据写入数据域中。这里还有一点需要注意的是:在类内,不管是否存在模板,类名都可以作为类型,但是为了避免混淆我们不建议这样使用。


      2. push_back和push_front

      由于我们需要在list类中的成员变量需要定义一个list_node<T>*类型的指针,而且我们在后面会经常用到list_node这种类型。所以在这里我们直接将这个类型typedef一下。

      💕 list类的整体框架:

      class list{
      public:
      	typedef list_node<T> node;
      	//成员方法...
      private:
      	node* _head;
      }
      
      //尾插
      void push_back(const T& x) const
      {
      	node* new_node = new node(x);
      	node* tail = _head->_prev;
      	//链接节点之间的关系
      	tail->_next = new_node;
      	new_node->_prev = tail;
      	new_node->_next = _head;
      	_head->_prev = new_node;
      }
      //头插
      void push_front(const T& x)
      {
      	node* head = _head->_next;
      	node* new_node = new node(x);
      	
      	_head->_next = new_node;
      	new_node->_prev = _head;
      	new_node->_next = head;
      	head->_prev = new_node;
      }
      

      这里的头插和尾插也很简单,因为和我们之前在数据结构时候的双向循环链表是一样的,只需要找到头或者尾,然后链接四个节点间的关系即可。


      3. 普通迭代器

      因为迭代器是类似于指针的存在,迭代器要实现指针相关的全部或者部分操作,+、-、++、- -、*、我们之前的string和vector使用的就是原生指针,所以他天然就支持上述的所有操作,但是list就不一样了。

      因为list的节点是一个结构体,同时list的每一个节点的物理地址是不连续的,所以如果我们直接使用普通的原生指针来作为list的迭代器的话就不能够进行,解引用、++、–等操作,所以我们需要将迭代器封装为一个类,在类中实现这些操作的运算符重载才能够得到最终的结果。

      template<class T>
      struct __list_iterator
      {
      	typedef list_node<T> node;
      	typedef __list_iterator<T> self;
      	//构造函数
      	__list_iterator(node* n)
      		:_node(n)
      	{}
      
      	node* _node;
      	//重载*运算符
      	T& operator*()
      	{
      		return _node->_val;
      	}
      
      	//重载前置++运算符
      	self& operator++()
      	{
      		_node = _node->_next;
      		return *this;
      	}
      
      	//重载后置++运算符
      	self operator++(int)
      	{
      		self tmp(*this);
      		_node = _node->_next;
      		return tmp;
      	}
      	
      	//重载前置--运算符
      	self& operator--()
      	{
      		_node = _node->_prev;
      		return *this;
      	}
      
      	//重载后置--运算符
      	self operator--(int)
      	{
      		self tmp(*this);
      		_node = _node->_prev;
      		return tmp;
      	}
      
      	//重载!=运算符
      	bool operator!=(const self& s)
      	{
      		return _node != s._node;
      	}
      
      	//重载==运算符
      	bool operator==(const self& s)
      	{
      		return _node == s._node;
      	}
      };
      

      我们实现一个简单的正向迭代器是很容易的,使用一个模板参数T表示类型,当然这里我们可以将__list_iterator<T>来typedef一下,方便后续使用。最后将这些运算符都重载一遍即可。

      普通迭代器封装好了之后,我们需要在list类中来实现它的begin()和end()方法。由于迭代器的名字一般都是iterator,而且对于范围for来说,也只能通过iterator来转换为迭代器进行遍历。所以这里我们将其typedef为iterator。

      typedef __list_iterator<T> iterator;
      
      iterator begin()
      {
      	return iterator(_head->_next);
      }
      
      iterator end()
      {
      	return iterator(_head);
      }
      

      4. const迭代器

      const迭代器与普通迭代器的区别在于const迭代器指向的内容是不能修改的,但是它的指向是可以修改的,但在这里有些人可能会投机取巧用以下的方式来实现const迭代器:

      typedef const iterator const_iterator;
      
      const_iterator begin() const
      {
      	return const_iterator(_head->_next);
      }
      
      const_iterator end() const
      {
      	return const_iterator(_head);
      }
      

      这里我们千万要注意这种方式是不行的。因为const修饰的是iterator的返回值,即iterator的指向是不能修改的,如果我们这样写的话那么迭代器就不能++和–操作了,而解引用后的内容依旧是可以修改的。

      在这里我们最好的做法就是在__list_iterator的类模板中的添加一个模板参数,然后再list类中typedef两份分别将第二个参数分别改成T&和const T&的类型,本质上就是让编译器根据传入的Ref的不同来自动示例化出const迭代器类,具体的解决做法如下:

      template<class T,class Ref>
      struct __list_iterator
      {
      	typedef list_node<T> node;
      	typedef __list_iterator<T,Ref> self;
      	//构造函数
      	__list_iterator(node* n)
      		:_node(n)
      	{}
      
      	node* _node;
      	//重载*运算符
      	Ref operator*()
      	{
      		return _node->_val;
      	}
      	//...
      };
      //list类中typedef两份
      typedef __list_iterator<T, T&> iterator;
      typedef __list_iterator<T, const T&> const_iterator;
      

      这里还有一个问题就是:如果我们需要重载一个->运算符,因为list中可能存储的是自定义类型,这个自定义类型如果要是有多个成员变量的话,我们就需要使用->来解引用访问成员变量。这里又出现问题了,因为又有普通迭代器和const迭代器的区分,所以为了解决同样的问题,我们同样选择多添加一个模板参数来解决这个问题。

      template<class T,class Ref,class Ptr>
      struct __list_iterator
      {
      	typedef list_node<T> node;
      	typedef __list_iterator<T,Ref,Ptr> self;
      	//构造函数
      	__list_iterator(node* n)
      		:_node(n)
      	{}
      
      	node* _node;
      	//重载*运算符
      	Ref operator*()
      	{
      		return _node->_val;
      	}
      	//重载->
      	Ptr operator->()
      	{
      		return &_node->_val;
      	}
      	//...
      };
      typedef __list_iterator<T, T&, T*> iterator;
      typedef __list_iterator<T, const T&,const T*> const_iterator;
      

      下面我们来总结一下完整版的list迭代器的实现:

      template<class T,class Ref,class Ptr>
      struct __list_iterator
      {
      	typedef list_node<T> node;
      	typedef __list_iterator<T,Ref,Ptr> self;
      	//构造函数
      	__list_iterator(node* n)
      		:_node(n)
      	{}
      
      	node* _node;
      	//重载*运算符
      	Ref operator*()
      	{
      		return _node->_val;
      	}
      	//重载->
      	Ptr operator->()
      	{
      		return &_node->_val;
      	}
      
      	//重载前置++运算符
      	self& operator++()
      	{
      		_node = _node->_next;
      		return *this;
      	}
      
      	//重载后置++运算符
      	self operator++(int)
      	{
      		self tmp(*this);
      		_node = _node->_next;
      		return tmp;
      	}
      	
      	//重载前置--运算符
      	self& operator--()
      	{
      		_node = _node->_prev;
      		return *this;
      	}
      
      	//重载后置--运算符
      	self operator--(int)
      	{
      		self tmp(*this);
      		_node = _node->_prev;
      		return tmp;
      	}
      
      	//重载!=运算符
      	bool operator!=(const self& s)
      	{
      		return _node != s._node;
      	}
      
      	//重载==运算符
      	bool operator==(const self& s)
      	{
      		return _node == s._node;
      	}
      };
      //list类内
      typedef __list_iterator<T, T&, T*> iterator;
      typedef __list_iterator<T, const T&,const T*> const_iterator;
      
      iterator begin()
      {
      	return iterator(_head->_next);
      }
      
      const_iterator begin() const
      {
      	return const_iterator(_head->_next);
      }
      
      iterator end()
      {
      	return iterator(_head);
      }
      
      const_iterator end() const
      {
      	return const_iterator(_head);
      }
      

      5. 增删查改(insert、erase、pop_back、pop_front)

      //指定位置插入
      void insert(iterator pos,const T& x)
      {
      	node* cur = pos._node;
      	node* prev = cur->_prev;
      	
      	node* new_node = new node(x);
      	prev->_next = new_node;
      	new_node->_prev = prev;
      	new_node->_next = cur;
      	cur->_prev = new_node;
      }
      //指定位置删除
      iterator erase(iterator pos)
      {
      	assert(pos != end());
      	node* prev = pos._node->_prev;
      	node* next = pos._node->_next;
      
      	prev->_next = next;
      	next->_prev = prev;
      
      	delete pos._node;
      	return iterator(next);
      }
      
      //尾删
      void pop_back()
      {
      	erase(--end());
      }
      
      //头删
      void pop_front()
      {
      	erase(begin());
      }
      

      7. 构造和析构

      默认构造

      由于我们将来在构造新的对象的时候会经常用到创建一个头结点的操作,所以这里我们在写默认无参构造的时候直接将它写成一个函数,以便于后面的调用。

      list()
      {
      	empty_Init();
      }
      void empty_Init()
      {
      	_head = new node;
      	_head->_next = _head;
      	_head->_prev = _head;
      }
      

      拷贝构造

      //拷贝构造传统写法
      list(const list<T>& lt)
      {
      	empty_Init();
      	for (auto e : lt)
      	{
      		push_back(e);
      	}
      }
      //拷贝构造现代写法
      list(const list<T>& lt)
      {
      	empty_Init();
      	list<T> tmp(lt.begin(), lt.end());
      	swap(tmp);
      }
      

      迭代器区间构造

      template <class Iterator>
      list(Iterator first, Iterator last)
      {
      	empty_Init();
      	while (first != last)
      	{
      		push_back(*first);
      		first++;
      	}
      }
      //交换函数
      void swap(list<T>& lt)
      {
      	std::swap(_head, lt._head);
      }
      

      用n个val来构造对象

      //用n个val构造对象
      list(int n, const T& val = T())
      {
      	empty_Init();
      	for (int i = 0; i < n; i++)
      	{
      		push_back(val);
      	}
      }
      

      赋值运算符重载

      //赋值运算符重载——传统写法
      list<T>& operator=(const list<T>& lt)
      {
      	if (this != &lt)
      	{
      		clear();
      		for (const auto& e : lt)
      		{
      			push_back(e);
      		}
      	}
      	return *this;
      }
      //赋值运算符重载
      list<T>& operator=(list<T> lt)//注意这里不能用引用
      {
      	swap(lt);
      	return *this;
      }
      

      析构函数

      //clear函数的实现
      void clear()
      {
      	iterator it = begin();
      	while (it != end())
      	{
      		it = erase(it);
      		//erase(it++);  这种写法也是可以的
      	}
      }
      //析构函数
      ~list()
      {
      	clear();
      	delete _head;
      	_head = nullptr;
      }
      

      size 和 empty

      //size()
      size_t size() const
      {
      	iterator it = begin();
      	size_t Size = 0;
      	while (it != end())
      	{
      		++Size;
      		++it;
      	}
      	return Size;
      }
      
      //empty
      bool empty() const
      {
      	return _head->_next == _head
      		&& _head->_prev == _head;
      }
      

      三、list模拟实现整体源码

      namespace cjl
      {
      	//节点的封装
      	template<class T>
      	struct list_node
      	{
      		list_node<T>* _prev;
      		list_node<T>* _next;
      		T _val;
      		//构造函数
      		list_node(const T& val = T())
      			:_prev(nullptr)
      			,_next(nullptr)
      			,_val(val)
      		{}
      	};
      
      	//迭代器的封装——普通迭代器
      	//迭代器可能是原生指针,也可能是自定义类型对原生指针的封装,模拟指针的行为
      	template<class T,class Ref,class Ptr>
      	struct __list_iterator
      	{
      		typedef list_node<T> node;
      		typedef __list_iterator<T,Ref,Ptr> self;
      		//构造函数
      		__list_iterator(node* n)
      			:_node(n)
      		{}
      
      		node* _node;
      		//重载*运算符
      		Ref operator*()
      		{
      			return _node->_val;
      		}
      		//重载->
      		Ptr operator->()
      		{
      			return &_node->_val;
      		}
      
      		//重载前置++运算符
      		self& operator++()
      		{
      			_node = _node->_next;
      			return *this;
      		}
      
      		//重载后置++运算符
      		self operator++(int)
      		{
      			self tmp(*this);
      			_node = _node->_next;
      			return tmp;
      		}
      		
      		//重载前置--运算符
      		self& operator--()
      		{
      			_node = _node->_prev;
      			return *this;
      		}
      
      		//重载后置--运算符
      		self operator--(int)
      		{
      			self tmp(*this);
      			_node = _node->_prev;
      			return tmp;
      		}
      
      		//重载!=运算符
      		bool operator!=(const self& s)
      		{
      			return _node != s._node;
      		}
      
      		//重载==运算符
      		bool operator==(const self& s)
      		{
      			return _node == s._node;
      		}
      	};
      	//迭代器的封装——const迭代器——这样写造成了严重的代码冗余
      	//template<class T>
      	//struct __list_const_iterator
      	//{
      	//	typedef list_node<T> node;
      	//	typedef __list_const_iterator<T> self;
      	//	//构造函数
      	//	__list_const_iterator(node* n)
      	//		:_node(n)
      	//	{}
      
      	//	node* _node;
      	//	//重载*运算符
      	//	const T& operator*()
      	//	{
      	//		return _node->_val;
      	//	}
      
      	//	//重载前置++运算符
      	//	self& operator++()
      	//	{
      	//		_node = _node->_next;
      	//		return *this;
      	//	}
      
      	//	//重载!=运算符
      	//	bool operator!=(const self& s)
      	//	{
      	//		return _node != s._node;
      	//	}
      	//};
      	template<class T>
      	class list
      	{
      	public:
      		typedef list_node<T> node;
      		typedef __list_iterator<T, T&, T*> iterator;
      		//typedef __list_const_iterator<T> const_iterator;
      		typedef __list_iterator<T, const T&,const T*> const_iterator;
      		iterator begin()
      		{
      			return iterator(_head->_next);
      		}
      
      		const_iterator begin() const
      		{
      			return const_iterator(_head->_next);
      		}
      
      		iterator end()
      		{
      			return iterator(_head);
      		}
      
      		const_iterator end() const
      		{
      			return const_iterator(_head);
      		}
      
      		//默认的无参构造
      		list()
      		{
      			empty_Init();
      		}
      
      		void empty_Init()
      		{
      			_head = new node;
      			_head->_next = _head;
      			_head->_prev = _head;
      		}
      
      		//用n个val构造对象
      		list(int n, const T& val = T())
      		{
      			empty_Init();
      			for (int i = 0; i < n; i++)
      			{
      				push_back(val);
      			}
      		}
      
      		//析构函数
      		~list()
      		{
      			clear();
      			delete _head;
      			_head = nullptr;
      		}
      
      		//拷贝构造
      		/*list(const list<T>& lt)
      		{
      			empty_Init();
      			for (auto e : lt)
      			{
      				push_back(e);
      			}
      		}*/
      
      		//拷贝构造——现代写法
      		list(const list<T>& lt)
      		{
      			empty_Init();
      			list<T> tmp(lt.begin(), lt.end());
      			swap(tmp);
      		}
      
      		//迭代器区间构造
      		template <class Iterator>
      		list(Iterator first, Iterator last)
      		{
      			empty_Init();
      			while (first != last)
      			{
      				push_back(*first);
      				first++;
      			}
      		}
      
      		赋值运算符重载——传统写法
      		//list<T>& operator=(const list<T>& lt)
      		//{
      		//	if (this != &lt)
      		//	{
      		//		clear();
      		//		for (const auto& e : lt)
      		//		{
      		//			push_back(e);
      		//		}
      		//	}
      		//	return *this;
      		//}
      
      		//赋值运算符重载
      		list<T>& operator=(list<T> lt)//注意这里不能用引用
      		{
      			swap(lt);
      			return *this;
      		}
      
      		//交换函数
      		void swap(list<T>& lt)
      		{
      			std::swap(_head, lt._head);
      		}
      
      		//尾插
      		void push_back(const T& x) const
      		{
      			node* new_node = new node(x);
      			node* tail = _head->_prev;
      			//链接节点之间的关系
      			tail->_next = new_node;
      			new_node->_prev = tail;
      			new_node->_next = _head;
      			_head->_prev = new_node;
      		}
      
      		//尾删
      		void pop_back()
      		{
      			erase(--end());
      		}
      
      		//头插
      		void push_front(const T& x)
      		{
      			node* head = _head->_next;
      			node* new_node = new node(x);
      
      			_head->_next = new_node;
      			new_node->_prev = _head;
      			new_node->_next = head;
      			head->_prev = new_node;
      			//insert(begin(), x);
      		}
      
      		//头删
      		void pop_front()
      		{
      			erase(begin());
      		}
      		
      		//指定位置插入
      		void insert(iterator pos,const T& x)
      		{
      			node* cur = pos._node;
      			node* prev = cur->_prev;
      			
      			node* new_node = new node(x);
      			prev->_next = new_node;
      			new_node->_prev = prev;
      			new_node->_next = cur;
      			cur->_prev = new_node;
      		}
      
      		//指定位置删除
      		iterator erase(iterator pos)
      		{
      			assert(pos != end());
      			node* prev = pos._node->_prev;
      			node* next = pos._node->_next;
      
      			prev->_next = next;
      			next->_prev = prev;
      
      			delete pos._node;
      			return iterator(next);
      		}
      
      		//clear函数的实现
      		void clear()
      		{
      			iterator it = begin();
      			while (it != end())
      			{
      				it = erase(it);
      				//erase(it++);  这种写法也是可以的
      			}
      		}
      
      		//size()
      		size_t size() const
      		{
      			iterator it = begin();
      			size_t Size = 0;
      			while (it != end())
      			{
      				++Size;
      				++it;
      			}
      			return Size;
      		}
      
      		//empty
      		bool empty() const
      		{
      			return _head->_next == _head
      				&& _head->_prev == _head;
      		}
      
      	private:
      		node* _head;
      	};
      }
      

      四、vector和list的区别

      【C++】list的使用 | 模拟实现


      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://chenjiale.blog.csdn.net/article/details/129566216,作者:星河万里᭄ꦿ࿐,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:增加PHP性能分析

      下一篇:【C++】C++11——右值引用和移动语义|可变参数模板

      相关文章

      2025-05-19 09:04:53

      查看RISC-V版本的gcc中默认定义的宏

      查看RISC-V版本的gcc中默认定义的宏

      2025-05-19 09:04:53
      c++ , linux
      2025-05-19 09:04:44

      使用DoubleLinkedList扩展类,允许Add,Remove,Contains

      使用DoubleLinkedList扩展类,允许Add,Remove,Contains

      2025-05-19 09:04:44
      class , list , null , 扩展
      2025-05-19 09:04:14

      【牛客网+LeetCode】链表 OJ强训题——高效解法

      【牛客网+LeetCode】链表 OJ强训题——高效解法

      2025-05-19 09:04:14
      数据结构 , 链表
      2025-05-16 09:15:10

      【C/C++算法】蓝桥杯之递归算法(如何编写想出递归写法)

      【C/C++算法】蓝桥杯之递归算法(如何编写想出递归写法)

      2025-05-16 09:15:10
      结点 , 递归 , 遍历 , 链表 , 题目
      2025-05-14 10:03:13

      数据结构-队列

      队列是仅限在一端进行插入,另一端进行删除的线性表。

      2025-05-14 10:03:13
      元素 , 入队 , 出队 , 链表 , 队列
      2025-05-13 09:50:28

      分隔链表-146. LRU 缓存

      给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

      2025-05-13 09:50:28
      int , key , LinkedHashMap , 缓存 , 节点 , 链表
      2025-05-13 09:50:17

      二叉树展开为链表

      二叉树展开为链表

      2025-05-13 09:50:17
      二叉树 , 单链 , 指针 , 结点 , 链表
      2025-05-12 10:19:12

      DS高阶:LRU Cache

      LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法。

      2025-05-12 10:19:12
      Cache , LRU , 使用 , 哈希 , 节点 , 迭代 , 链表
      2025-05-12 09:10:14

      排序链表,23. 合并 K 个升序链表,146. LRU 缓存

      给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

      2025-05-12 09:10:14
      key , lt , 升序 , 链表
      2025-05-12 09:10:14

      环形链表 II,21. 合并两个有序链表,2. 两数相加

      给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

      2025-05-12 09:10:14
      lt , pos , 节点 , 链表
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5223133

      查看更多

      最新文章

      【C/C++算法】蓝桥杯之递归算法(如何编写想出递归写法)

      2025-05-16 09:15:10

      数据结构-队列

      2025-05-14 10:03:13

      代码 测试用例 测试结果 测试结果 两两交换链表中的节点

      2025-05-09 09:30:19

      数据结构知识点

      2025-05-08 09:03:07

      leetcode链表相关题目

      2025-04-22 09:28:19

      【C++】STL----list常见用法

      2025-04-22 09:24:51

      查看更多

      热门文章

      Lambda函数

      2023-02-08 10:33:56

      QT中多线程的使用

      2023-02-07 10:34:04

      0030 简单的四则运算 c/c++

      2023-03-21 10:39:47

      C++虚函数知识点总结

      2023-02-21 06:21:46

      (10)Qt对象模型

      2023-02-13 07:55:59

      【C&C++】二进制数据的位运算(如何存储字符)

      2023-04-10 08:53:37

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      c/c++入门算法经典---蛇形填数

      C语言解题 || 逼近π

      【C++】string的使用及其模拟实现

      P1032 字串变换(C++_BFS_剪枝)

      C++:标识符命名规则(5)

      不多见但是实用的部分C函数(2)

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号