1、概念:带头双向循环链表

定义链表
template <class T>
class list
{
typedef ListNode<T> Node;
public:
typedef listIterator<T, T&, T*> iterator;
typedef listIterator<T, const T&, const T*> const_iterator;
public:
Node* _head;
}
函数声明
//容量相关
bool empty() const;
// 增删查
void push_back(const T& val);
void pop_back();
void push_front(const T& val);
void pop_front();
// 获取首尾元素
T& front();
const T& front() const;
T& back();
const T& back() const;
// 迭代器
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
函数实现
构造函数
list()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
析构函数
~list()
{
// 链表中的数据还没清理,这样会导致内存泄漏
/*delete _head;
_head = nullptr;*/
clear();
delete _head;
_head = nullptr;
}
清空链表
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
}
插入删除
void push_back(const T& val)
{
// _head tail newnode
Node* tail = _head->_prev;
Node* newnode = new Node(val);
tail->_next = newnode;
newnode->_prev = tail;
_head->_prev = newnode;
newnode->_next = _head;
}
void pop_back()
{
// _head prev tail
Node* tail = _head->_prev;
Node* prev = tail->_prev;
prev->_next = _head;
_head->_prev = prev;
}
void push_front(const T& val)
{
// _head newnode next
Node* next = _head->_next;
Node* newnode = new Node(val);
_head->_next = newnode;
newnode->_prev = _head;
newnode->_next = next;
next->_prev = newnode;
}
void pop_front()
{
// _head first second
Node* first = _head->_next;
_head->_next = first->_next;
first->_prev = _head;
}


获取首尾元素
// 可读可写
T& front()
{
return _head->_next->_val;
}
// 只读
const T& front() const
{
return _head->_next->_val;
}
// 可读可写
T& back()
{
return _head->_prev->_val;
}
// 只读
const T& back() const
{
return _head->_prev->_val;
}

迭代器
链表这里的迭代器不和string和vector的迭代器一样,string和vector是连续的物理空间,迭代器就是指针,对迭代器的++和--操作都是符合指针的运算。链表这里就不能像原生指针这样计算,因为链表的物理空间是不连续的。
所以链表的迭代器要自定义类型。
template <class T>
struct listIterator
{
typedef ListNode<T> Node;
Node* _node;
listIterator(Node* node)
:_node(node)
{
// 用来调试打断点的
int x = 10;
}
T& operator*()
{
return _node->_val;
}
T* operator->()
{
return &_node->_val;
}
// ++it
listIterator& operator++()
{
_node = _node->_next;
return *this;
}
// it++
listIterator operator++(int)
{
listIterator tmp(*this);
_node = _node->_next;
return tmp;
}
// --it
listIterator& operator--()
{
_node = _node->_prev;
return *this;
}
// it--
listIterator operator--(int)
{
listIterator tmp(*this);
_node = _node->_prev;
return tmp;
}
bool operator!=(listIterator it)
{
return _node != it._node;
}
};

如何定义const迭代器呢?
const迭代器的成员函数和普通迭代器一样,只是返回值有差异。
一种方法就是定义一个自定义的const_iterator类型,结果就是代码很冗余,可读性差。
另一种方式就是使用模板来解决这个问题。
template <class T, class Ref, class Ptr>
struct listIterator
{
typedef ListNode<T> Node;
Node* _node;
listIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_val;
}
Ptr operator->()
{
return &_node->_val;
}
// ++it
listIterator<T,Ref,Ptr>& operator++()
{
_node = _node->_next;
return *this;
}
// it++
listIterator<T, Ref, Ptr> operator++(int)
{
listIterator tmp(*this);
_node = _node->_next;
return tmp;
}
// --it
listIterator<T, Ref, Ptr>& operator--()
{
_node = _node->_prev;
return *this;
}
// it--
listIterator<T, Ref, Ptr> operator--(int)
{
listIterator tmp(*this);
_node = _node->_prev;
return tmp;
}
bool operator!=(listIterator it)
{
return _node != it._node;
}
};

任意位置插入删除
iterator insert(iterator pos, const T& val)
{
// prev newnode cur
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* newnode = new Node(val);
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return pos;
}
iterator erase(iterator pos)
{
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
// prev cur next
prev->_next = next;
next->_prev = prev;
delete cur;
// 这样导致迭代器失效了
//return pos;
// 返回下一个位置的迭代器
return iterator(next);
}
标准库中erase后是返回下一个位置的迭代器:

标准库中insert后是返回新插入元素的迭代器:
