STL中list的模拟实现

1. 前言and框架

首先,我们要明白list的本质是什么,list的本质是带头双向循环链表

  • 注意事项
  1. 类模板的声明:在类前面加一个模板template<class T>即可
  2. 需要创建一个类list,但list的底层是带头双向循环链表。链表则需要结点,那我们就还需要创建要给结点的类。【总结:就是在列表list中有一个头结点的指针。一个结点里面又会有数据,前一个,后一个结点指针】
  3. 这是自己模拟实现的,则需要有命名空间,否则编译器会调用库里的list
  4. 如果类里面的内容都是公有的,那么则可以使用struct。有公有和私有,那么使用class(这是惯例,但不是规定)。在struct中,如果没有对某个内容用限定符修饰,那么它就是私有。
  5. 一共两个类。list_node(结点)和list(列表)
namespace hou
{
   
	template<class T>
	struct list_node
	{
   
	    //在list_node中,存放这个结点的数据,前一个和后一个结点指针,
		T _data;
		list_node<T>* _next;
		list_node<T>* _prev;
	};

	template<class T>
	class list
	{
   
		typedef list_node<T> Node;
	private:
		Node* _head;
	};
}
  1. typedef list_node<T> Node;这一步是为了防止大家忘记写模板参数< T>。
    在class中,class没有用限定符修饰,是私有的。因此,只有在这个类里面才可以用Node,在这个类里面Node才代表list_node<T>.

  2. 为什么list_node的所有成员全部对外开放?
    因为链表list在增删查改的时候需要高频地控制list_node的成员变量。如果list_node的成员都私有的话,则需要友元函数,比较麻烦。
    但是全部对外开放,不害怕别人修改你的数据吗?
    其实是很难修改的。我们在使用list的时候,是感知不到底层的结点,哨兵位之类的东西的。我们只是看到了它的各种接口,可以感知到它是双向的。想修改内容,需要知道变量的名称,命名空间的名字。所以,虽然开放,但是也安全。

  3. list中大部分用迭代器。在此之前,有迭代器失效这个概念,这里也会出现。但string中也有迭代器失效,但比较少,因为大部分用下标访问,较少使用迭代器。vector也有迭代器失效。

2. 相对完整的框架

  1. 牢记牢记牢记:为了方便,我们已经将list_node<T>在list这个类里面typedefNode
  2. 给list构造(无参):
		void empty_init()
		{
   
			_head = new Node();   //_head的类型是Node*(也就是list_node<T>)结点的指针
			_head->_prev = _head;
			_head->_next = _head;
		}
		list()
		{
   
			empty_init();
		}
  1. list_node的构造
		list_node(const T& x = T())
			:_data(x)
			,_next(nullptr)
			,_prev(nullptr)
		{
   }
  1. 迭代器
    面向对象的三大特征:封装,继承,多态。
    封装可以用类和迭代器来实现。(它可以用来“屏蔽底层的实现细节,屏蔽个容器的结构差异,本质是封装底层细节和差异,提供同一的访问方式)

只需要提供一个结点即可
在这里插入图片描述

namespace hou
{
   
	template<class T>
	struct list_node
	{
   
		T _data;
		list_node<T>* _next;
		list_node<T>* _prev;
		list_node(const T& x = T())
			:_data(x)
			,_next(nullptr)
			,_prev(nullptr)
		{
   }
	};
	template<class T>
	struct list_iterator
	{
   
		typedef list_node<T> Node;
		Node* _node;
	}; 
	template<class T>
	class list
	{
   
		typedef list_node<T> Node;
	public:
		typedef list_iterator<T> iterator; 
		void empty_init()
		{
   
			_head = new Node();   //_head的类型是Node*(也就是list_node<T>)结点的指针
			_head->_prev = _head;
			_head->_next = _head;
		}
		list()
		{
   
			empty_init();
		}
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值