list类设计
template<class _Ty>
class list
{
private:
struct _Node; //声明结构体
typedef struct _Node* _Nodeptr; //声明结构体类型指针
struct _Node
{
_Nodeptr _Prev, _Next;
_Ty _Value;
};
struct _Acc;
struct _Acc
{
typedef struct _Node*& _Nodepref; //指针的引用
typedef _Ty& _Vref; //值的引用
static _Vref _Value(_Nodeptr _p)
{
return (*_p)._Value;
}
static _Nodepref _Prev(_Nodeptr _p)
{
return (*_p)._Prev;
}
static _Nodepref _Next(_Nodeptr _p)
{
return (*_p)._Next;
}
};
迭代器的使用
迭代器分别有:普通迭代器与常性迭代器
public:
typedef _Ty value_type;
typedef _Ty& reference;
typedef const _Ty& const_reference;
typedef _Ty* pointer;
typedef const _Ty* const_pointer;
public:
class iterator;
class const_iterator;
class const_iterator //常性迭代器
{
protected:
_Nodeptr _Ptr;
public:
const_iterator(_Nodeptr _P):_Ptr(_P)
{}
const_reference operator*()const //常引用进行返回
{
return _Acc::_Value(_Ptr);
}
const_pointer operator->()
{
return &**this;
}
const_iterator& operator++()
{
_Ptr = _Acc::_Next(_Ptr);
return *this;
}
const_iterator& operator--()
{
_Ptr = _Acc::_Prev(_Ptr);
return *this;
}
const_iterator operator++(int)
{
const_iterator tmp = *this;
++* this;
return tmp;
}
const_iterator operator--(int)
{
const_iterator tmp = *this;
--* this;
return tmp;
}
bool operator==(const const_iterator& _X)const
{
return this->_Ptr == _X._Ptr;
}
bool operator!=(const const_iterator& _X)const
{
return !(*this == _X);
}
_Nodeptr _Mynode()const
{
return _Ptr;
}
};
class iterator:public const_iterator //is a
{
public:
iterator(_Nodeptr _P) :const iterator(_P) {}
reference operator*() const
{
return _Acc::_Value(_Ptr);
}
pointer operator->()const
{
return &**this;
}
iterator& operator++()
{
_Ptr = _Acc::_Next(_Ptr);
return *this;
}
iterator operator++(int)
{
iterator tmp = *this;
++* this;
return tmp;
}
iterator& operator--()
{
_Ptr = _Acc::Prev(_Ptr);
return *this;
}
iterator operator--(int)
{
iterator tmp = *this;
--* this;
return tmp;
}
bool operator==(const iterator& _X)const
{
return this->_Ptr == _X._Ptr;
}
bool operator!=(const iterator & _X)const
{
return !(*this == _X);
}
};
list类实现
当我们创建一个链表,此时size大小为0,head指向一个_Node,并且该节点的前驱后继都指向自己
public:
list()_Head(_Buynode()),_Size(0)
{}
private:
_Nodeptr _Head;
size_t _Size;
_Nodeptr _Buynode(_Nodeptr _Parg = NULL, _Nodeptr _Narg = NULL) //空间申请
{
_Nodeptr _S = (_Nodeptr)malloc(sizeof(_Node));
_Acc::_Prev(_S) = _Prag == NULL ? _S : _Prag;
_Acc::_Next(_S) = _Narg == NULL ? _S : _Narg;
return _S;
}
void _Freenode(_Nodeptr P)
{}
};
这里会出现一个问题,也就是若构造类为模板类。那么派生类不可以直接使用继承得到的积累数据和方法,需要通过this指针使用,否则会出现“找不到标识符”错误
所以在我们 iterator
类 继承 const_iterator
类 后,对父类保护成员的使用_Nodeptr _Ptr;
,需要加上this指针 this->_Ptr
,或者 const_iterator::_Ptr
通过迭代器进行前插
iterator insert(iterator _P, const _Ty& val)
{
_Nodeptr _S = _P._Mynode();
_Acc::_Prev(_S) = _Buynode(_Acc::_Prev(_S), _S);//_P的前驱更新为新节点 并且将新结点的前驱后继一同设置完毕
_S = _Acc::_Prev(_S);//此处将_S指向新结点
_Acc::_Next(_Acc::_Prev(_S)) = _S; //将新结点的前驱的 _Next 节点设置为新结点
new(&_Acc::_Value(_S)) _Ty(val); //_Acc::_Value(_S) = val; 设计类型无法直接赋值
return _P;
}
上面行代码分别解决了①②③,三个指针的设置,继而只剩下最后一个_Next
之所以使用定位new:若我们list中成员属于设计类型无法直接赋值,需要构建对象进行赋值,在_Value空间地址,构建_Ty类型对象,可以类比为以下
int *p = (int*)malloc(sizeof(int));
new(p) int(12); //在p地址,构建int类型对象
尾插与头插方法
void push_front(const _Ty& val)
{
insert(begin(), val);
}
void push_back(const _Ty& val)
{
insert(end(), val);
//对于双向循环链表,在头结点前插入就是尾插
}
完整代码
list大部分功能进行完善,包括迭代器、插入、删除、交换、列表初始化等等
#pragma once
#include<initializer_list>
namespace zyq
{
template<class T>
void Swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
template<class _Ty>
class list
{
protected:
struct _Node; //声明结构体
typedef struct _Node* _Nodeptr; //声明结构体类型指针
struct _Node
{
_Nodeptr _Prev, _Next;
_Ty _Value;
};
struct _Acc;
struct _Acc
{
typedef struct _Node*& _Nodepref; //指针的引用
typedef _Ty& _Vref; //值的引用
static _Vref _Value(_Nodeptr _p)
{
return (*_p)._Value;
}
static _Nodepref _Prev(_Nodeptr _p)
{
return (*_p)._Prev;
}
static _Nodepref _Next(_Nodeptr _p)
{
return (*_p)._Next;
}
};
public:
typedef _Ty value_type;
typedef _Ty& reference;
typedef const _Ty& const_reference;
typedef _Ty* pointer;
typedef const _Ty* const_pointer;
public:
class iterator;
class const_iterator;
friend class iterator;
friend class const_iterator;
class const_iterator //常性迭代器
{
protected:
_Nodeptr _Ptr;
public:
const_iterator(_Nodeptr _P = NULL):_Ptr(_P)
{}
const_reference operator*()const //常引用进行返回
{
return _Acc::_Value(_Ptr);
}
const_pointer operator->()
{
return &**this;
}
const_iterator& operator++()
{
_Ptr = _Acc::_Next(_Ptr);
return *this;
}
const_iterator& operator--()
{
_Ptr = _Acc::_Prev(_Ptr);
return *this;
}
const_iterator operator++(int)
{
const_iterator tmp = *this;
++* this;
return tmp;
}
const_iterator operator--(int)
{
const_iterator tmp = *this;
--* this;
return tmp;
}
bool operator==(const const_iterator& _X)const
{
return this->_Ptr == _X._Ptr;
}
bool operator!=(const const_iterator& _X)const
{
return !(*this == _X);
}
_Nodeptr _Mynode()const
{
return _Ptr;
}
};
class iterator :public const_iterator //is a
{
public:
iterator(_Nodeptr _P = NULL) :const_iterator(_P) {}
reference operator*() const
{
return _Acc::_Value(this->_Ptr);
}
pointer operator->()const
{
return &**this;
}
iterator& operator++()
{
this->_Ptr = _Acc::_Next(this->_Ptr);
return *this;
}
iterator operator++(int)
{
iterator tmp = *this;
++* this;
return tmp;
}
iterator& operator--()
{
this->_Ptr = _Acc::Prev(this->_Ptr);
return *this;
}
iterator operator--(int)
{
iterator tmp = *this;
--* this;
return tmp;
}
bool operator==(const iterator& _X)const
{
return this->_Ptr == _X._Ptr;
}
bool operator!=(const iterator & _X)const
{
return !(*this == _X);
}
};
iterator begin()
{
return iterator(_Acc::_Next(_Head));
}
iterator end()
{
return iterator(_Head);
}
const_iterator begin()const
{
return iterator(_Acc::_Next(_Head));
}
const_iterator end()const
{
return iterator(_Head);
}
public:
list(std::initializer_list<_Ty> list):list() //列表方式初始化
{
for (auto& x : list)
{
push_back(x);
}
}
list():_Head(_Buynode()),_Size(0)
{}
list(size_t count,const _Ty&val) :list() //c11
{
insert(begin(), count, val);
}
list(const _Ty* _F, const _Ty* _L) :list()
{
insert(begin(), _F, _L);
}//int ar[10]={12,23,34,45,56,67,78,89,90,100};
list(const list& _X) :_Head(_Buynode()), _Size(0)
{
insert(begin(), _X.begin(), _X.end());
}
list& operator=(const list _X)
{
if (this == &_X) return *this;
iterator _F1 = begin();
iterator _L1 = end();
const_iterator _F2 = _X.begin();
const_iterator _L2 = _X.end();
for (; _F1 != _L1 && _F2 != _L2; ++_F1, ++_F2)
{
*_F1 = *_F2;
}//深拷贝,其中一方结束
erase(_F1, _L1); //被拷贝结束,拷贝者后面节点删除
insert(_L1, _F2, _L2); //拷贝者结束,将被拷贝后面节点插入拷贝者
}
~list()
{
clear();
_Freenode(_Head);
}
iterator insert(iterator _P, const _Ty& val)
{
_Nodeptr _S = _P._Mynode();
_Acc::_Prev(_S) = _Buynode(_Acc::_Prev(_S), _S);//_P的前驱更新为新节点 并且将新结点的前驱后继一同设置完毕
_S = _Acc::_Prev(_S);//此处将_S指向新结点
_Acc::_Next(_Acc::_Prev(_S)) = _S; //将新结点的前驱的 _Next 节点设置为新结点
new(&_Acc::_Value(_S)) _Ty(val); //_Acc::_Value(_S) = val;
_Size++;
return _P;
}
iterator insert(iterator _P, size_t count, const _Ty& val)
{
while (count--)
{
insert(_P, val);
}
return _P;
}
iterator insert(iterator _P, const_iterator _F, const_iterator _L)
{
while (_F++ != _L)
{
insert(_P, _Acc::_Value(_F));
}
}
void insert(iterator _P, std::initializer_list<_Ty> list)//使用系统的初始化列表
{
for (auto& x : list)
{
insert(_P, x);
}
}//ilist.insert(ilist.begin(),{12,23,34,45,56,67,78,89,90})
void push_front(const _Ty& val)
{
insert(begin(), val);
}
void push_back(const _Ty& val)
{
insert(end(), val);
}
void pop_front()
{
erase(begin());
}
void pop_back()
{
erase(--end());
}
void clear()
{
erase(begin(), end());
}
void remove(const _Ty& val)
{
iterator _F = begin(), _L = end();
while (_F != _L)
{
if (*_F == val)
{
erase(_F);
break;
}
_F++;
}
}
void remove_all(const _Ty& val)
{
iterator _F = begin(), _L = end();
while (_F != _L)
{
if (*_F == val)
{
erase(_F++); //删除后_F会变成失效指针,因为该节点已经被删除
}
else
{
++_F;
}
}
}
iterator erase(iterator _P)
{
_Nodeptr _S = _P++._Mynode();
_Acc::_Next(_Acc::_Prev(_S)) = _Acc::_Next(_S);
_Acc::_Prev(_Acc::_Next(_S)) = _Acc::_Prev(_S);
(&_Acc::_Value(_S))->~Ty(); //释放节点对应数据 进行析构
_Freenode(_S);
return _P;
}
iterator erase(iterator _F, iterator _L)
{
while (_F != _L)
{
erase(_F++);
}
}
void Swap(list& _X)
{
zyq::Swap(this->_Head, _X._Head);
zyq::Swap(this->_Size, _X._Size);
}
private:
_Nodeptr _Head;
size_t _Size;
_Nodeptr _Buynode(_Nodeptr _Parg = NULL, _Nodeptr _Narg = NULL) //空间申请
{
_Nodeptr _S = (_Nodeptr)malloc(sizeof(_Node));
_Acc::_Prev(_S) = _Parg == NULL ? _S : _Parg;
_Acc::_Next(_S) = _Narg == NULL ? _S : _Narg;
return _S;
}
void _Freenode(_Nodeptr _P)
{
free(_P);
}
};
}
就地构造
int main()
{
std::list<Object> alist;
Object a(10);
alist.push_back(a);
return 0;
}
以上程序执行,首先构建一个Object对象,随后拷贝构造一个对象在list中
int main()
{
std::list<Object> alist;
alist.push_back(Object(10));
alist.emplace_back(12); //就地构建 只创建一次
return 0;
}
通过无名对象进行入队,首先会构建一个对象,然后通过移动拷贝构造将此对象的资源进行转移至链表的value值;而就地构造是直接调动构建函数,在结点位置直接构建对象