1.List介绍
list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
list在任意位置插入和删除元素效率高。
list缺点是不能支持随机访问元素。
2.List包含的成员
由于List是双向循环带头链表,所以成员有一个哨兵位结点。
Node* _head;
3.List结点初始化封装
因为在创建一个结点时,需要对结点内的内容进行初始化,所以需要封装一个结构体来方便我们每次创建结点并初始化。而链表中的一个结点具有三个成员,一个是存储的数据,一个是指向上一个结点的指针,一个是指向下一个结点的指针。
template<class T>
struct ListNode
{
T _data;
ListNode<T>* _next;
ListNode<T>* _prev;
ListNode(const T& x = T())
:_data(x)
, _next(nullptr)
, _prev(nullptr)
{}
};
4.List迭代器与反向迭代器封装
与其他容器相同,List也具有迭代器,通过迭代器就可以依次访问到List中的数据,而为了便于操作,与第三点相同,也是封装一个结构体来实现迭代器的功能。而反向迭代器是基于正向迭代器来实现的,只要一个容器具备正向迭代器就能通过复用来实现反向迭代器的功能。
template<class T,class Ref,class Ptr>
struct __List_iterator
{
typedef ListNode<T> Node;
typedef __List_iterator<T,Ref,Ptr> iterator;
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef ptrdiff_t difference_type;
Node* _node;
__List_iterator(Node* node)
:_node(node)
{}
bool operator!=(const iterator& it) const
{
return _node != it._node;
}
bool operator==(const iterator& it) const
{
return _node == it._node;
}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(operator*());
}
iterator& operator++()
{
_node = _node->_next;
return *this;
}
iterator operator++(int)
{
iterator tmp(*this);
_node = _node->_next;
return tmp;
}
iterator& operator--()
{
_node = _node->_prev;
return *this;
}
iterator operator--(int)
{
iterator tmp(*this);
_node = _node->_prev;
return tmp;
}
};
namespace L
{
template <class Iterator, class Ref, class Ptr>
struct __Reverse_Iterator
{
Iterator _it;
typedef __Reverse_Iterator<Iterator, Ref, Ptr> RIterator;
__Reverse_Iterator(Iterator it)
:_it(it)
{}
RIterator& operator++()
{
--_it;
return *this;
}
RIterator operator++(int)
{
Iterator tmp = _it;
--_it;
return tmp;
}
RIterator& operator--()
{
++_it;
return *this;
}
RIterator operator--(int)
{
Iterator tmp = _it;
++_it;
return tmp;
}
Ref operator*()
{
Iterator tmp = _it;
--tmp;
return *tmp;
}
Ptr operator->()
{
return &(operator*());
}
bool operator!=(const RIterator& rit) const
{
return _it != rit._it;
}
bool operator==(const RIterator& rit) const
{
return _it == rit._it;
}
};
}
为了实现const版本的迭代器,因此模板参数需要三个,T,T&,T*。
值得一提的是,在正向迭代器中begin指向头节点的下一个,end指向头节点,而反向迭代器是复用了正向迭代器的begin和end,因此形成了对称关系,所以反向迭代器解引用是解引用上一个结点。
5.构造函数
typedef ListNode<T> Node;
List()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
(1)拷贝构造函数
void EmptyInit()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
template <class InputIterator>
List(InputIterator first, InputIterator last)
{
EmptyInit();
while (first != last)
{
push_back(*first);
++first;
}
}
void swap(List<T>& lt)
{
::swap(_head, lt._head);
}
List(const List<T>& lt)
{
EmptyInit();
List<T> tmp(lt.begin(), lt.end());
swap(tmp);
}
利用迭代器区间、swap交换函数、初始化函数来进行拷贝构造list。
6.插入函数
(1)任意位置插入
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 iterator(NewNode);
}
返回值设计成返回插入结点的迭代器,防止发生迭代器失效问题。
(2)尾插
void push_back(const T& x)
{
/*Node* _tail = _head->_prev;
Node* NewNode = new Node(x);
_head->_prev = NewNode;
NewNode->_next = _head;
_tail->_next = NewNode;
NewNode->_prev = _tail;*/
insert(end(), x);
}
可以直接复用插入函数。
(3)头插
void push_front(const T& x)
{
insert(begin(), x);
}
7.删除函数
(1)任意位置删除
iterator erase(iterator pos)
{
assert(pos != end());
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
next->_prev = prev;
prev->_next = next;
delete cur;
return iterator(next);
}
(2)头删
void pop_front()
{
erase(begin());
}
(3)尾删
void pop_back()
{
erase(--end());
}
8.析构函数及其他特殊接口
(1)析构函数
在实现析构函数之前可以实现一下clear()函数,功能是清空list中的有效数据,而析构函数是清空list包括头结点。
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
}
~List()
{
clear();
delete _head;
_head = nullptr;
}
析构函数直接复用clear()函数。
(2)迭代器
typedef __List_iterator<T, T&, T*> iterator;
typedef __List_iterator<T, const T&, const T*> const_iterator;
typedef __Reverse_Iterator<iterator, T&, T*> RIterator;
typedef __Reverse_Iterator<iterator, const T&, const T*> Const_RIterator;
const_iterator begin() const
{
return const_iterator(_head->_next);
}
const_iterator end() const
{
return const_iterator(_head);
}
iterator begin()
{
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
Const_RIterator rbegin() const
{
return Const_RIterator(end());
}
Const_RIterator rend() const
{
return Const_RIterator(begin());
}
RIterator rbegin()
{
return RIterator(end());
}
RIterator rend()
{
return RIterator(begin());
}