C++ list简单模拟实现

1.list的特点

list的本质就是带头双向链表,可以在常数时间复杂度进行插入删除的容器。

  • list和forward_list最主要的区别:forward_list是单链表,只能向前迭代,但list可以双向迭代
  • list比其他序列式容器(array,vector,deque)进行插入,移除元素的执行效率更好
  • list不支持任意位置的随机访问,要访问中间的元素,需要从头或者尾按序遍历

2.list中的节点

给于_val默认值,前后指针置空(使用struct,默认访问限定符是public)

cpp 复制代码
	//节点
	template <class T>
	struct ListNode
	{
		ListNode(const T& val = T())
		{
			_prev = nullptr;
			_next = nullptr;
			_val = val;
		}

		ListNode* _prev;//指向上一个元素
		ListNode* _next;//指向下一个元素
		T _val;		//值
	};

3.list中的迭代器

迭代器是一种设计模式 ,它在底层指针和用户接口之间增加了一个抽象层。这个抽象层让算法(如 std::sort, std::find)可以统一处理不同容器,而不需要知道容器内部是如何存储数据的。迭代器的实质就是指针,指向每个节点。(注意operator*返回的是T&)

cpp 复制代码
	//迭代器
	template<class T>
	struct List_Iterator
	{
		using Node = ListNode<T>;
		using self = List_Iterator<T>;

		List_Iterator(Node* node)
			:_node(node)
		{}
		//不需要析构函数,没有自己开辟空间,用默认构造就行

		//++it
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		//it++
		self operator++(int)
		{
			self tmp(this);
			_node = _node->_next;

			return tmp;
		}

		//--it
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		//it--
		self operator--(int)
		{
			self tmp(this);
			_node = _node->_prev;
			return tmp;
		}

		bool operator==(const self& it)
		{
			return it._node == _node;
		}

		bool operator!=(const self& it)
		{
			return it._node != _node;
		}

		const T& operator*()
		{
			return  _node->_val;
		}


		Node* _node;
	};

4.list的构造析构函数

  • 默认构造就是先创建一个头节点,让前后指针指向自己
  • 拷贝构造就是把一个链表节点的值全部尾插
cpp 复制代码
	template <class T>
	class List
	{
    public:
		using Node = ListNode<T>;
		using  Iterator = List_Iterator<T>;
		List()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			//前后指针指向自己
		}

		List(List<T>& list)//拷贝构造
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			for ( auto e : list)
			{
				push_back(e);
			}	
		}

		~List()//析构函数
		{
			clear();

			assert(_head);
			delete _head;
			_head = nullptr;
		}
		void clear()//释放所有节点
		{
			auto it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}
	 private:
		    Node* _head;//哨兵节点

    };

5.list的增删改

insert

在迭代器pos处插入val值。尾插和头插直接复用insert即可

cpp 复制代码
		Iterator insert(Iterator it, const T& val)
		{
			Node* newnode = new Node(val);
			Node* cur = it._node;
			Node* prev = it._node->_prev;

			//prev newnode cur
			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;

			//返回新节点的迭代器
			return newnode;
		}
		//头插
		void push_front(const T& val)
		{
			insert(begin(), val);

		}

		//尾插
		void push_back(const T& val)
		{
			insert(end(), val);
		}

erase

删除迭代器pos处的值。对于头删和尾删同理复用

cpp 复制代码
		Iterator erase(Iterator it)
		{
			assert(it != _head);

			Node* cur = it._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;
			prev->_next = next;
			next->_prev = prev;

			delete cur;

			return next;

		}
		//头删
		void pop_front()
		{
			erase(begin());
		}
		
		//尾删
		void pop_back()
		{
			erase(--end());
		}
相关推荐
Bella的成长园地2 小时前
面试中关于 c++ async 的高频面试问题有哪些?
c++·面试
彷徨而立2 小时前
【C/C++】什么是 运行时库?运行时库 /MT 和 /MD 的区别?
c语言·c++
qq_417129252 小时前
C++中的桥接模式变体
开发语言·c++·算法
Hello World . .3 小时前
数据结构:队列
c语言·开发语言·数据结构·vim
No0d1es5 小时前
电子学会青少年软件编程(C语言)等级考试试卷(三级)2025年12月
c语言·c++·青少年编程·电子学会·三级
you-_ling6 小时前
数据结构:4.二叉树
数据结构
bjxiaxueliang6 小时前
一文掌握C/C++命名规范:风格、规则与实践详解
c语言·开发语言·c++
senijusene6 小时前
数据结构与算法:队列与树形结构详细总结
开发语言·数据结构·算法
青桔柠薯片6 小时前
数据结构:队列,二叉树
数据结构
杜家老五6 小时前
综合实力与专业服务深度解析 2026北京网站制作公司六大优选
数据结构·算法·线性回归·启发式算法·模拟退火算法