【c++】list模拟实现

list的接口

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{
	template<class T>
	struct listnode    
	{
		listnode* <T>_next;
		listnode* <T>_prev;
		T _data;
		listnode(const T& x = T())
			:_prev(nulllptr)
			,_next(nullptr)
			,_data(x)
		{
		
		
		
		
		}






	};
	template<class T>
	struct _list_iterator
	{
		typedef listnode <T>node;
		
		typedef _list_iterator<T>self;
		node* _node;
		_list_iterator(node* n)
			:_node(n)
		{
		}
		self& operator++()
		{
		}

		self& operator--()
		{
		}
		self operator++(int)
		{
		}
		self operator--(int)
		{
		}
		bool operator!=(const self& s)
		{
		
		}
		bool operator==(const self& s)
		{

		}
		T& operator()
		{
		
		}





	};
     template <class T>
	 class list
	 {    typedef listnode <T>node;
	  public:
		 typedef _list_iterator<T>  iterator;
		 list()
		 {
			 empty_init();

		 
		 }
		 void empty_init()
		 {
		 
		 
		 }
		 iterator begin()
		 {
		 
		 }
		 iterator end()
		 {
		 
		 
		 
		 }
		 void clear()
		 {
		 
		 
		 }
		 ~list
		 {
		 
		 
		 }
		 list(const list<T>& it)
		 {
		 
		 
		 }
		 void push_back(const T&x)
		 {
		 
		 
		 
		 }
		 void push_front(const T& x)
		 {



		 }
		 void pop_back()
		 {
		 
		 
		 
		 }
		 void pop_front()
		 {
		 
		 
		 
		 
		 }
		 void swap(list<T>& tmp)
		 {
			 

		 }
		 list<T>& operator=(list<T>it)
		 {
		 
		 
		 
		 }
		 iterator insert(iterator pos ,const T&x)
		 {
		 
		 
		 
		 
		 
		 }
		 iterator erase(iterator pos)
		 {
		 
		 
		 
		 
		 }
	 private :
		 node* _head;


	 };



}

迭代器前置++,前置–,后置++,后置–

self& operator++()
		{ 

		  _node= _node->next;
		  return * this;



		}

		self& operator--()
		{
			_node = _node->_prev;
			return * this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;


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

迭代器重载等于,以及不等于,以及解引用访问数据

         bool operator!=(const self& s)
		{
			return s._node != _node;
		
		}
		bool operator==(const self& s)
		{
			return s._node == _node;
		}
		T& operator*()
		{
			return _node->_data;
		
		}
		

链表的默认构造,以及尾插,获取链表的头和尾巴,以及测试尾插函数

 list()
		 {
			 empty_init();

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

		 
		 
		 }
		 iterator begin()
		 {
			 return _head->_next;
		 
		 }
		 iterator end()
		 {
			 return _head;
		 
		 
		 }
		 	 void push_back(const T&x)
		 {
			 node* newnode = new node(x);
			 node* tail = _head->_prev;
			 newnode->_next = _head;
			 newnode->_prev = tail;
			 tail->_next = newnode;
			 _head->_prev = newnode;
			 
		 
		 
		 
		 }

尾插测试,以及迭代器测试

 void test1()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout <<*it << " ";
			 it++;
		  }
 
	 }

在这里插入图片描述


const迭代器的实现

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/811e5adc5cac4d7d82a43a8790aa1741.png

我们就可以新增两个带const的begin(),end(),权限平移就可以调动。

	 iterator begin() const
		 {
			 return _head->_next;

		 }
		 iterator end() const
		 {
			 return _head;


		 }

如果我们要修改迭代器所指向位置的值呢??
在这里插入图片描述
我们应该如何模拟实现一个常量迭代器呢??
如果按照以下的方式,可以实现吗??
在这里插入图片描述

所以我们应该怎么实现呢??
在这里插入图片描述
迭代器中的解引用函数,我们需要让他的返回值不被修改,所以 这个函数的返回值加const 就好了,所以我们在实现一个类,这个类基本和普通迭代器的类一样,只是在解引用函数上有区分。

	template<class T>
	struct const_list_iterator
	{
		typedef    listnode <T>  node;



		typedef const_list_iterator<T> self;


		node* _node;
		const_list_iterator(node* n)
			:_node(n)
		{
		}
		self& operator++()
		{

			_node = _node->_next;
			return *this;



		}

		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;


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

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

		}
		bool operator==(const self& s)
		{
			return s._node == _node;
		}
		const T operator*()
		{
			return _node->_data;

		}
	};

在这里插入图片描述

在这里插入图片描述
这样子,就实现了const 的迭代器,但是重新搞一个类好麻烦呀,于是有大佬就想出了在提供一个模板参数来解决这个问题
在这里插入图片描述


->运算符重载函数

我们可以想一下什么时候会用到->,当指针it指向的是结构体的话,我们可以访问使用
it->data,来访问数据,也可先对指针解引用*it,*it表示拿到这个结构体,然后使用.来访问(*it).data;

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

		}
	 struct AA
	 {
		 int a1;
		 int a2;
		 AA(int _a1=0,int _a2=0)
			 :a1(_a1)
			 ,a2(_a2)
		 
		 {
		 
		 }




	 };

测试->

	 void test3()
	 {
		 list<AA>res; 
		 res.push_back(AA(1,1));
		 res.push_back(AA(2, 2));
		 res.push_back(AA(3, 3));
		 res.push_back(AA(4, 4));
		 list<AA> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << it.operator->()->a1<<":" << it.operator->()->a2 << endl;
			 it++;
	 }
 
	 
	 }

在这里插入图片描述
在这里插入图片描述


这里有一个问题就是->访问也是取数据,但取到的数据能修改吗?这就面临和解引用取数据同样的问题。
我们现在需要做的是const迭代器的不能被将修改,普通的可以修改值
在这里插入图片描述
我发现这里和解引用那里不一样的是,解引用那里是值不可被修改,这里是地址不可被修改
在这里插入图片描述


=运算符重载赋值

	 void swap(list<T>& tmp)
		 {
			 std::swap(_head, tmp._head);

		 }
		 list<T>& operator=(list<T>it)
		 {

			 swap(it);
			 return *this;
		 
		 
		 
		 }

赋值函数测试

 void test4()
	 {
		
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 list<int> ret = res;
		 list<int> ::iterator it = ret.begin();
		 while (it != ret.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
		
	 
	 
	 
	 }

在这里插入图片描述


拷贝构造函数

	 list(const list<T>& it)
		 {

			 empty_init();
			 for (auto e : it)
			 {
				 push_back(e);
			 }
		 
		 }

这里与赋值不一样的地方是赋值的话,之前的空间不用放着也没用,就在原空间操作了;拷贝构造是重新开的空间,然后将原来数据尾插到新空间
拷贝构造函数测试

 void test5()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 list<int> ret(res);
		 list<int> ::iterator it = ret.begin();
		 while (it != ret.end())
		 {
			 cout << *it << " ";
			 it++;
         }

	 
	 
	 }

在这里插入图片描述


insert函数和earse函数

因为之前写的双向链表就是借鉴的这里,如果逻辑不清楚,可以去看一下双向链表那一篇文章
(insert)
在这里插入图片描述

 iterator insert(iterator pos ,const T&x)
		 {
			 node* cur = pos._node;
			 node* prev = cur->_prev;
			 node* newnode = new node(x);
			 newnode->_next = cur;
			 newnode->_prev = prev;
			 prev->_next = newnode;
			 cur->_prev = newnode;
			 return newnode;
		 
		 
		 
		 
		 }

(earse)
在这里插入图片描述

 iterator erase(iterator pos)
		 {
			 assert(pos != end());
			 node* cur = pos._node;
			 node* prev = cur->_prev;
			 node* next = cur->_next;
			 prev->_next = next;
			 next->_prev = prev;
			 delete cur;
			 return next;
		 
		 
		 
		 
		 }

这里insert函数迭代器不会失效,而earse函数迭代器会失效,最好earse完,给迭代器传下一个位置的地址。


析构函数

 void clear()
		 { 
			 iterator it = begin();
			 while (it != end())
			 {
				 it = earse(it);//释放完一个结点,返回下一个结点地址
			 }
		 
		 }
		 ~list()
		 {
			 clear();//完成后只剩头节点
			 delete _head;//释放头节点
			 _head = nullptr;//防止野指针
			 cout<<"析构完成“<<endl;
		 
		 }

析构测试

	 void test8()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);

		
		 
		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << *it << " ";
			 it++;
		 }
		 res.~list();
	 
	 
	 
	 
	 
	 }

在这里插入图片描述


push_front函数,pop_back()函数,pop_front()函数

因为实现了insert和earse,所以这三个就简单了。

 void push_front(const T& x)
		 {
			 insert(begin(), x);



		 }
		 void pop_back()
		 {
			 erase(--end());
		 
		 
		 }
		 void pop_front()
		 {
		 
			 erase(begin());
		 
		 
		 }

注意这里的end()是最后一个数据的下一个位置,所以要先–
测试头插

 void test6()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 
		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
		 cout << endl;
		 res.push_front(1000);
		 list<int> ::iterator num = res.begin();
		 while (num != res.end())
		 {
			 cout << *num << " ";
			 num++;






		 }
	 
	 
	 
	 
	 }

在这里插入图片描述
测试头删和尾删

void test7()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);

		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
		 cout << endl;
		 res.pop_front();
		 res.pop_back();
		 list<int> ::iterator num = res.begin();
		 while (num != res.end())
		 {
			 cout << *num << " ";
			 num++;






		 }




	 }

在这里插入图片描述
测试这三个间接测试了insert和erase


源码展示

list.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace zjw
{
	template<class T>
	struct listnode
	{
		listnode<T>* _next;
		listnode<T>* _prev;
		T _data;
		listnode(const T& x = T())
			:_prev(nullptr)
			,_next(nullptr)
			,_data(x)
		{
		
		
		
		
		}






	};
	template<class T ,class res,class ptr>
	struct _list_iterator
	{ 
		typedef    listnode <T>  node;



		typedef _list_iterator<T,res,ptr> self;
		
		
		
		node* _node;
		_list_iterator(node* n)
			:_node(n)
		{
		}
		self& operator++()
		{ 

		  _node= _node->_next;
		  return * this;



		}

		self& operator--()
		{
			_node = _node->_prev;
			return * this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;


		}
		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_prev;
			return tmp;
			
		}
		bool operator !=(const self& s)
		{
			return s._node != _node;
		
		}
		bool operator==(const self& s)
		{
			return s._node == _node;
		}
		res  operator*()
		{
			return _node->_data;
		
		}
	    ptr  operator->()
		{
			return &_node->_data;

		}

	};
	



	
	
     template <class T>
	 class list
	 {
		 typedef    listnode <T>  node;
	 public:
		 typedef _list_iterator<T,T&,T*>  iterator;
		 typedef _list_iterator<T,const T&,const T*>  const_iterator;
		
		 list()
		 {
			 empty_init();

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

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

		 }
		 const_iterator  end() const
		 {
			 return _head;


		 }
		 iterator erase(iterator pos)
		 {
			 assert(pos != end());
			 node* cur = pos._node;
			 node* prev = cur->_prev;
			 node* next = cur->_next;
			 prev->_next = next;
			 next->_prev = prev;
			 delete cur;
			 return next;




		 }
		 void clear()
		 { 
			 iterator it = begin();
			 while (it != end())
			 {
				 it=erase(it);
			 }
		 
		 }
		 ~list()
		 {
			 clear();
			 delete _head;
			 _head = nullptr;
			 cout << "析构完成" << endl;
		 
		 }
		 list(const list<T>& it)
		 {

			 empty_init();
			 for (auto e : it)
			 {
				 push_back(e);
			 }
		 
		 }
		 void push_back(const T&x)
		 {
			 node* newnode = new node(x);
			 node* tail = _head->_prev;
			 newnode->_next = _head;
			 newnode->_prev = tail;
			 tail->_next = newnode;
			 _head->_prev = newnode;
			 
		 
		 
		 
		 }
		 void push_front(const T& x)
		 {
			 insert(begin(), x);



		 }
		 void pop_back()
		 {
			 erase(--end());
		 
		 
		 }
		 void pop_front()
		 {
		 
			 erase(begin());
		 
		 
		 }
		 void swap(list<T>& tmp)
		 {
			 std::swap(_head, tmp._head);

		 }
		 list<T>& operator=(list<T>it)
		 {

			 swap(it);
			 return *this;
		 
		 
		 
		 }
		 iterator insert(iterator pos ,const T&x)
		 {
			 node* cur = pos._node;
			 node* prev = cur->_prev;
			 node* newnode = new node(x);
			 newnode->_next = cur;
			 newnode->_prev = prev;
			 prev->_next = newnode;
			 cur->_prev = newnode;
			 return newnode;
		 
		 
		 
		 
		 }
	
	 private :
		 node* _head;


	 };
	 struct AA
	 {
		 int a1;
		 int a2;
		 AA(int _a1 = 0, int _a2 = 0)
			 :a1(_a1)
			 , a2(_a2)

		 {

		 }




	 };
	 void print_list(const list<AA>it)
	 {
		 list<AA>::const_iterator res =it.begin();
		 while (res!=it.end())
		 {
			
			 cout << res.operator->()->a1 << ":" << res->a2 << endl;
			 res++;







		 }
	 }
	/* void test1()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		  list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout <<*it << " ";
			 it++;
		 





		 }

	 
	 
	 
	 
	 
	 
	 
	 
	 }*/
	 //void test2()
	 //{
		// list<int>res;
		// res.push_back(1);
		// res.push_back(2);
		// res.push_back(3);
		// res.push_back(4);
		// print_list(res);
	 //
	 //
	 //
	 //
	 //
	 //}

	/* void test3()
	 {
		 list<AA>res; 
		 res.push_back(AA(1,1));
		 res.push_back(AA(2,2));
		 res.push_back(AA(3, 3));
		 res.push_back(AA(4, 4));
	
		 print_list(res);
		 }*/

	/* void test4()
	 {
		
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 list<int> ret = res;
		 list<int> ::iterator it = ret.begin();
		 while (it != ret.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
		
	 
	 
	 
	 }*/
	/* void test5()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 list<int> ret(res);
		 list<int> ::iterator it = ret.begin();
		 while (it != ret.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
	

	 
	 
	 }*/
	/* void test6()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);
		 
		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
		 cout << endl;
		 res.push_front(1000);
		 list<int> ::iterator num = res.begin();
		 while (num != res.end())
		 {
			 cout << *num << " ";
			 num++;






		 }
	 
	 
	 
	 
	 }*/
	/* void test7()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);

		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << *it << " ";
			 it++;






		 }
		 cout << endl;
		 res.pop_front();
		 res.pop_back();
		 list<int> ::iterator num = res.begin();
		 while (num != res.end())
		 {
			 cout << *num << " ";
			 num++;






		 }




	 }*/
	 void test8()
	 {
		 list<int>res;
		 res.push_back(1);
		 res.push_back(2);
		 res.push_back(3);
		 res.push_back(4);

		
		 
		 list<int> ::iterator it = res.begin();
		 while (it != res.end())
		 {
			 cout << *it << " ";
			 it++;
		 }
		 res.~list();
	 
	 
	 
	 
	 
	 }


	 



}

.cpp

#include"list.h"
int main()
{

	zjw::test8();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#小多子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值