C++ 仿写 std::list


#include <iostream>

using namespace std;

template<class _Ty>
class List 
{
protected:
	struct _Node;//先声明一个节点类型的结构体,在下一行进行重命名
	typedef _Node* _Nodeptr;//这里重命名为_Nodeptr,别名之后可以通过名字知道他是一个指向结构体的指针
	struct _Node {
		_Nodeptr _Next, _Prev;
		_Ty _Value;
	};//std标准给的list是双向链表,该结构体中存储的是该节点的前驱和后继
	struct _Acc {
		typedef _Nodeptr& _Nodepref;
		typedef _Ty& _Vref;
		static _Nodepref _Next(_Nodeptr _P) {
			return ((_Nodepref)(*_P)._Next);
		}
		static _Nodepref _Prev(_Nodeptr _P) {
			return ((_Nodepref)(*_P)._Prev);
		}
		static _Vref _Value(_Nodeptr _P) {
			return ((_Vref)(*_P)._Value);
		}
	};//该结构体中有三个方法,分别返回节点的前驱,后继。因为我们一般取前驱的时候是node->prev,重点在node上,而该方法调用的时候是 _Acc::_Prev(node),我们先看到的是Prev。侧重点是前驱。
public:
	class iterator {//内部类
	public:
		iterator() {}//迭代器的无参构造
		iterator(_Nodeptr _P) :_Ptr(_P) {}//通过指针构造迭代器
		_Ty& operator*()const {
			return (_Acc::_Value(_Ptr));
		}//重载*运算符,使得当我们*iterator的时候可以获得当前迭代器指向节点的值
		iterator& operator++() {
			_Ptr = _Acc::_Next(_Ptr);
			return *this;
		}//重载前置++,返回下一个节点的位置
		iterator operator++(int) {
			iterator _Tmp = *this;
			++* this;
			return _Tmp;
		}//重载后置++,返回当前节点。但是迭代器已经+1
		iterator& operator--() {
			_Ptr = _Acc::_Prev(_Ptr);
			return *this;
		}//同前置++
		iterator operator--(int) {
			iterator _Tmp = *this;
			--* this;
			return _Tmp;
		}//同后置++
		bool operator==(const iterator& _X) {
			return _Ptr == _X._Ptr;
		}//重载==号,返回是否相等
		bool operator!=(const iterator& _X) {
			return (!(*this == _X));
		}//重载!=号
		_Nodeptr _Mynode()const {
			return (_Ptr);
		}//获取当前节点的节点位置
	protected:
		_Nodeptr _Ptr;//每个迭代器其实内部都是结构体指针
	};
public://构造函数
	explicit List():_Head(_Buynode()),_Size(0)
	{}//无参构造函数
	explicit List(size_t _N, const _Ty& _V = _Ty()) :_Head(_Buynode()), _Size(0) {
		insert(begin(), _N, _V);
	}//通过元素和元素数量构造 记为构造1
	List(const _Ty* _F, const _Ty* _L):_Head(_Buynode()),_Size(0) {
		insert(begin(), _F, _L);
	}//通过数组构造链表 记为 构造2
	typedef iterator _It;//重命名迭代器为_It
	List(_It _F, _It _L) : _Head(_Buynode()), _Size(0)
	{
		insert(begin(), _F, _L);
	}//通过迭代器构造链表 记为构造3
public:
	void insert(iterator _P, _It _F, _It _L) {
		for (; _F != _L; ++_F) {
			insert(_P, *_F);//调用底层insert函数
		}构造3的insert
	}//
	void insert(iterator _P, const _Ty* _F, const _Ty* _L) {
		for (; _F != _L; ++_F) {
			insert(_P, *_F);//调用底层构造函数
		}
	}//构造2的insert
	void insert(iterator _P, size_t _M, const _Ty& _X)
	{
		for (; _M > 0; _M--) {
			insert(_P, _X);//调用底层构造函数
		}
	}//构造3的insert
	iterator insert(iterator _P, const _Ty& _X = _Ty()) {
		_Nodeptr _S = _P._Mynode();
		_Acc::_Prev(_S) = _Buynode(_S, _Acc::_Prev(_S));
		_S = _Acc::_Prev(_S);
		_Acc::_Next(_Acc::_Prev(_S)) = _S;
		_Acc::_Value(_S) = _X;
		++_Size;
		return (iterator(_S));
	}//队链表进行插入的时候底层都是
	iterator begin()
	{
		return (iterator(_Acc::_Next(_Head)));
	}//获取当前起始节点的迭代器,即结点指针封装后的迭代器。双链表头结点的后继就是起始节点
	iterator end() 
	{
		return (iterator(_Head));
	}//头节点就是最后一个节点的指向
	void push_front(const _Ty& _X)
	{
		insert(begin(), _X);
	}//在链表头部插入元素,就是在第一个元素的位置插入
	void push_back(const _Ty& _X)
	{
		insert(end(), _X);
	}//在头节点位置插入的时候就是尾插
protected:
	_Nodeptr _Buynode(_Nodeptr _Narg = 0, _Nodeptr _Parg = 0) {
		_Nodeptr _T = (_Nodeptr)malloc(1 * sizeof(_Node));
		_Acc::_Next(_T) = _Narg != 0 ? _Narg : _T;
		_Acc::_Prev(_T) = _Parg != 0 ? _Parg : _T;
		return(_T);
	}//每次构造一个节点,并通过传入的元素初始化该节点
protected:
	_Nodeptr _Head;//链表的元素包括头节点
	size_t _Size;//链表的大小
};
int main() 
{
	List<int> l1;
	List<int> l2(5, 6);
	int arr[5] = { 0,1,2,3,4 };
	List<int>::iterator iter;

	List<int> l3(arr, arr + 5);//_Ty*
	List<int> l4(l2.begin(),l2.end());
	l3.push_back(9999);
	l3.push_front(8888);
	for (iter = l3.begin(); iter != l3.end(); iter++)
	{
		cout << *iter << " ";
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值