list模拟实现

这篇博客详细介绍了如何从头开始模拟实现C++中的list容器,包括结点类(_list_node)用于存储数据和指针,迭代器类(_iterator)提供对链表的访问,以及list类(_list)的实现,包括begin()、end()、拷贝构造函数和赋值运算符重载等关键接口。通过这种方式,可以深入理解list的内部工作原理。
摘要由CSDN通过智能技术生成

     目录

准备工作:

 1.结点类

 2.迭代器类

 3.list类

        3.1 begin()和end()

         3.2拷贝构造和赋值操作符重载

        4. 完整代码


  为了更好的学会使用list和了解list的底层结构,我对list的一些常用接口进行了一个模拟实现。

准备工作:

        编写的list由三个类组成,结点类(_list_node),迭代器类(_iterator)和list类(_list)

为什么需要这三个类?

       1. 首先说明list底层是一个带头双向循环链表,是由一个一个的结点组成的,所以需要一个结点类。

        2.由于链表不能进行下标访问,迭代时需要用到迭代器进行访问,并且有的函数参数需要迭代器作为参数,所以需要一个迭代器类。

 1.结点类

        由于list是带头双向循环链表,结点类中需要包含两个指针和一个值来保存数据。一个指针保存前一个结点地址,一个指针保存下一个结点地址。

 2.迭代器类

        迭代器成员变量实际是一个结点的指针,只是将其封装起来变成一个类,里面重载了许多操作符函数,使其使用起来,像一个指针。

        为了可任意得到const迭代器和普通迭代器,我们在其模板使用了三个参数。如果使用一个参数,就会需要再写一个const迭代器类。

        怎么实现的const和普通迭代器共用一个模板呢?

 3.list类

        list类的成员变量也是一个结点指针,并且是头节点的指针。

3.1 begin()和end()

 

 3.2拷贝构造和赋值操作符重载

4. 完整代码

#include<iostream>
#include<assert.h>

using namespace std;

namespace my{
	//结点信息
	template<class T>
	struct __list_node{
		//构造函数
		__list_node(const T& val = T())
		:_next(nullptr)
		, _prev(nullptr)
		, _val(val)
		{}
		//结点成员变量
		__list_node* _prev;
		__list_node* _next;
		T _val;
	};

	//迭代器
	//为了同时实现iterator和const_iterator,模板含有三个变量
	template<class T, class Ref, class Ptr>
	struct _iterator{
		typedef _iterator<T, Ref, Ptr> Self;
		typedef __list_node<T> Node;
		//成员变量
		Node* _node;

		_iterator(Node* node=nullptr)
			:_node(node)
		{}
		_iterator(const Self& it)
			:_node(it._node)
		{}

		Ref operator*(){
			return _node->_val;
		}
		Ptr operator->(){
			return &_node->_val;
		}

		bool operator==(const _iterator& x)const{
			return _node == x._node;
		}
		bool operator!=(const _iterator& x)const{
			return _node != x._node;
		}
		//前置++
		Self& operator++(){
			_node = _node->_next;
			return *this;
		}
		//后置++
		Self operator++(int){
			Self tmp(_node);
			_node = _node->_next;
			return tmp;
		}
		//前置--
		Self& operator--(){
			_node = _node->_prev;
			return *this;
		}
		//后置--
		Self operator--(int){
			Self tmp(_node);
			_node = _node->_prev;
			return tmp;
		}

	};

	template<class T>
	class _list{
	public:
		//const迭代器
		typedef _iterator<T, const T&, const T*> const_iterator;
		//普通迭代器
		typedef _iterator<T, T&, T*> iterator;
		typedef __list_node<T> Node;
	public:
		//构造函数因为要构建对象,所以要给头节点动态申请空间
		_list(){
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}
		_list(int n, const T& val){
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;

			while (n){
				push_back(val);
				n--;
			}
		}

		template<class inputiterator>
		_list(inputiterator start, inputiterator end){
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;

			while (start != end){
				push_back(*start);
				start++;
			}
		}

		_list(const _list<T>& lt){
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;

			const_iterator it = lt.begin();
				while (it != lt.end()){
					push_back(*it);
					it++;
				}
			
		}
		~_list(){
			//先把结点删了,再删头节点
			clear();
			delete _head;
			_head = nullptr;
		}
		//返回迭代器开始和结尾。写画图
		//不能直接返回_head->next,这个不是迭代器类型
		iterator begin(){
			return iterator(_head->_next);
			//return _head->_next;
		}
		iterator end(){
			return iterator(_head);
		}
		const_iterator begin()const{
			return const_iterator(_head->_next);
		}
		const_iterator end()const{
			return const_iterator(_head);
		}

		_list<T>& operator=(_list<T>& lt){
			//先将结点清楚,剩下一个头节点
			clear();
			//拷贝构造一个
			_list<T> tmp(lt);
			swap(_head, tmp._head);
			return *this;
		}
		void clear(){
			iterator it = begin();
			while (it != end()){

				erase(it++);
				//迭代器失效
				//it++;
			}
			
		}
		void push_back(const T& val){

			//Node* tail = _head->_prev;
			//创建一个新节点
			//Node* newnode = new Node(val);

			//tail->_next = newnode;
			//newnode->_next = _head;
			//newnode->_prev = tail;
			//_head->_prev = newnode;
			//传迭代器参数
			insert(end(), val);

		}

		void pop_back(){

			erase(end()--);
		}
		void push_front(const T& val){
			insert(begin(), val);

		}
		void pop_front(){
			erase(begin());
		}

		iterator insert(iterator pos, const T& val){
			//拿到pos里的结点
			Node* cur = pos._node;
			Node* newnode = new Node(val);

			Node* prev = cur->_prev;
			

			prev->_next = newnode;
			newnode->_prev = prev;
			newnode->_next = cur;
			cur->_prev = newnode;
			//返回迭代器,用迭代器构造一个
			return iterator(newnode);
		}
		iterator erase(iterator pos){
			assert(pos != end());
			Node* cur = pos._node;
			Node* next = cur->_next;
			Node* prev = cur->_prev;

			prev->_next = next;
			next->_prev = prev;
			delete cur;
			
			return iterator(next);
		}
		size_t size(){
			size_t len = 0;
			for (auto c : *this){
				len++;
			}
			return len;
		}
		bool empty(){
			return _head->_next == _head;
		}

	private:
		Node* _head;
	};

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值