C++-----MySTL实现(6)-----list的实现
1、相关
在STL中,list是一个双向带环链表。list不能像vector那样使用普通指针作为迭代器,因为其节点在存储空间中不一定连续存在,list的迭代器必须有能力指向list的节点,这样才能正确的递增(指向下一个节点)、递减(指向上一个节点)、取值成员(取节点的数据值)存取等操作,由于STL list是一个双向链表,迭代器必须具备前移,后移的能力,所以list的迭代器类型是bidirectional_iterator_tag(可双向移动)。
设计过链表的应该知道,链表的节点和链表其实是两个东西,所以在这里的设计也是需要将其分开的。list的节点设计为局有两个指针域和一个数据域,两个指针一个指向前一个节点,一个指向后一个节点。list是一个双向链表,所以我们只需要一个指针既可以完整的表现整个链表。所以在list的本身的实现中只有一个指向节点的指针。在STL里有一个所谓的前闭后开的区间原则,但是对于一个环状的链表而言它并不存在这样的特性怎么办,其实很简单,只需要加上一个空白节点,这样就可以符合其前闭后开的原则,第一个节点就是这个空白节点的下一个节点,而最后一个节点是这个节点的前一个节点,这个节点是不可访问的,所以看起来list是一个双向的不带环链表,但其实是有环的。
特别需要注意的几个函数,一个是元素迁移函数,transfer和接合函数splice这两个函数是实现merge、reverse、sort的基础,list由于不能使用标准库的sort只能定义自己的sort,这个sort代码虽然不多,但是设计的很精妙,有点类似于归并,但是又不同。具体的解析可以参考(https://blog.csdn.net/shoulinjun/article/details/19501811)。侯捷老师的书上说使用的快排,但是源码并没有看出有快排的特征。
2、代码
/*
*list的实现
*/
#ifndef LIST_H_
#define LIST_H_
#include "allocator.h"
#include "iterator.h"
#include <initializer_list>
namespace MySTL {
//节点结构
template<class _T>
struct _list_node {
_list_node<_T>* prev; //指向前一个节点
_list_node<_T>* next; //指向后一个节点
_T data; //数据
};
//list迭代器
template<class _T, class _Ref, class _Ptr>
struct _list_iterator {
typedef _list_iterator<_T, _T&, _T*> iterator;//迭代器
typedef _list_iterator<_T, const _T&, const _T*> const_iterator;//常量迭代器
typedef _list_iterator<_T, _Ref, _Ptr> self;//引用
//没有继承迭代器的泛化接口,所以需要自己定义下面几种类型。
typedef bidirectional_iterator_tag iterator_category;
typedef _T value_type;
typedef _Ptr pointer;
typedef _Ref reference;
typedef _list_node<_T>* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
link_type node; //其实就是指向节点的指针
// 迭代器的构造函数
//如有参数,便根据参数设定迭代器与容器之间的联结关系
_list_iterator(link_type x) : node(x) {}
_list_iterator() {}
_list_iterator(const iterator& x) : node(x.node) {}
//迭代器操作
bool operator==(const self&x) const { return node == x.node };
bool operator!=(const self& x) const { return node != x.node; }
//对迭代器取值
reference operator*() const { return (*node).data; }
pointer operator->() const { return &(operator*()); }
//对迭代器累加就是前进一个节点
self& operator++() {//前置++
node = (link_type)((*node).next);
return *this;
}
self operator++(int) {//后置++
self temp = *this;
++*this; //这个++其实是重载的上面的++,但是*并不是重载的上面的*
return temp;
}
// 对迭代器累减1,就是后退一个节点
self& operator--()
{
node = (link_type)((*node).prev);
return *this;
}
self operator--(int)
{
self tmp = *this;
--*this;
return tmp;
}
};
//至此迭代器设计完成
//以下为list的设计
template <class _T, class _Alloc = alloc> // 默认使用 alloc 为配置器
class list {
protected:
typedef void* void_pointer;
typedef _list_node<_T> list_node;
// 专属配置器,每次配置一个节点大小
typedef simple_alloc<list_node, _Alloc> list_node_allocator;
public:
typedef _T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef list_node* link_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public:
typedef _list_iterator<_T, _T&, _T*> iterator;
typedef _list_iterator<_T, const _T&, const _T*> const_iterator;
protected:
//配置一个节点,返回其指针,使用的是二级配置器
link_type get_node() { return list_node_allocator::allocate(); }
//释放一个节点
void put_node(link_type p) { return list_node_allocator::deallocate(p); }
//配置一个带有元素值的节点
link_type creat_node(const _T& x) {
link_type p = get_node();
try {
//construct接受一个指针和一个初值,将初值设定到指针所指的空间上
construct(&p->data, x);
}
catch(...){
put_node(p);
throw;
}
return p;
}
//释放一个节点,并摧毁对象
void destroy_node(link_type p) {
destroy(&p->data);
put_node(p);
}
protected:
//以下为三个初始化函数
void empty_initialize() //空链表
{
node = get_node(); // 配置一个节点空间,令 node 指向它。
node->next = node; // 令node 头尾都指向自己,不设元素值。
node->prev = node;
}
//初始化为n个value元素
void fill_initialize(size_type n, const _T& value)
{
empty_initialize();
try
{
insert(begin(), n, value);
}
catch (...)
{
clear();
put_node(node);
throw;
}
}
//初始化两个迭代器范围内的链表
template <class _InputIterator>
void range_initialize(_InputIterator first, _InputIterator last)
{
empty_initialize();
try
{
insert(begin(), first, last);
}
catch (...)
{
clear();
put_node(node);
throw;
}
}
protected:
link_type node; // 永远指向尾后节点。该节点无元素值,代表空节点。
// 其 next 节点永远是头节点。这样只需要一个指针就可以表示整个链表
public:
//构造函数
list() { empty_initialize(); } // 产生一个空链表。
iterator begin() { return (link_type)((*node).next); }
const_iterator begin() const { return (link_type)((*node).next); }
iterator end() { return node; }// node 指向尾节点的下一位置
const_iterator end() const { return node; }
bool empty() const { return node->next == node; }
size_type size() const {
size_type result = size_type(distance(begin(), end()));//全局函数
return result;
}
size_type max_size() const { return size_type(-1); } //2^32
//取头结点的值
reference front() { return *begin(); }
const_reference front() const {return *begin()}
//取尾节点的值
reference back() { return *(--end());}
const_reference back() const { return *(--end()); }
//交换
void swap(list<_T, _Alloc> &x) { std::swap(node, x.node); }
//以下为insert的多个重载形式
//在迭代器position所指节点的前面位置插入一个节点,值为x,
iterator insert(iterator position, const _T& x) {
link_type tmp = creat_node(x); //创建一个节点,值为x
tmp->next = position.node;
tmp->prev = position.node->prev;
(link_type)(position.node->prev)->next = tmp;
position.node->prev = tmp;
return tmp;
}
// 在迭代器 position 所指位置之前安插一个节点,值为list值类型的默认值
iterator insert(iterator position) { return insert(position, _T()); }
//在迭代器 position 所指位置之前插入范围[first,last)内的值,在后面实现
template <class _InputIterator>
void insert(iterator position, _InputIterator first, _InputIterator last);
// 在迭代器 position 所指位置之前安插n个节点,值为 x,在后面实现
void insert(iterator pos, size_type n, const _T& x);
void insert(iterator pos, int n, const _T& x)
{
insert(pos, (size_type)n, x);
}
void insert(iterator pos, long n, const _T& x)
{
insert(pos, (size_type)n, x);
}
//安插一个节点作为头结点
void push_front(const _T& x) { insert(begin(), x); }
// 安插一个节点,做为尾节点
void push_back(const _T& x) { insert(end(), x); }
// 移除迭代器 position 所指节点
iterator erase(iterator position)
{
link_type next_node = link_type(position.node->next);
link_type prev_node = link_type(position.node->prev);
prev_node->next = next_node;
next_node->prev = prev_node;
destroy_node(position.node);
return iterator(next_node);
}
//移除范围内迭代器,在后面实现
iterator erase(iterator first, iterator last);
//重新调整链表大小,new_size比原来大,扩充至new_size,并填以值x
//new_size比原来小,缩减至new_size,摧毁靠后节点,三个函数都在后面实现
void resize(size_type new_size, const _T& x);
void resize(size_type new_size) { resize(new_size, _T()); }
void clear();
//移除头结点
void pop_front() { erase(begin()); }
//移除尾节点,end()其实是指向那个空节点的。
void pop_back()
{
iterator tmp = end();
erase(--tmp);
}
//构造函数,都使用fill_initialize来构造,因为不是默认类型,所以不能使用全局的初始化函数
list(size_type n, const _T& value) { fill_initialize(n, value); }
list(int n, const _T& value) { fill_initialize(n, value); }
list(long n, const _T& value) { fill_initialize(n, value); }
explicit list(size_type n) { fill_initialize(n, _T()); }
//范围构造,
template <class _InputIterator>
list(_InputIterator first, _InputIterator last)
{
range_initialize(first, last);
}
list(const list<_T, _Alloc>& x)
{
range_initialize(x.begin(), x.end());
}
//列表构造
list(const std::initializer_list<_T>& l)
{
range_initialize(l.begin(), l.end());
}
//析构函数
~list()
{
clear();
put_node(node);
}
//拷贝赋值构造函数
list<_T, _Alloc>& operator=(const list<_T, _Alloc>& x);
protected:
// 将 [first,last) 内的所有元素搬移到position 处。是splice、sort、merge的基础
void transfer(iterator position, iterator first, iterator last)
{
if (position != last) {
(*(link_type((*last.node).prev))).next = position.node;
(*(link_type((*first.node).prev))).next = last.node;
(*(link_type((*position.node).prev))).next = first.node;
link_type tmp = link_type((*position.node).prev);
(*position.node).prev = (*last.node).prev;
(*last.node).prev = (*first.node).prev;
(*first.node).prev = tmp;
}
}
public:
// 将 x 接合于 position 所指位置之前
// x 必须不同于 *this。
void splice(iterator position, list& x)
{
if (!x.empty())
transfer(position, x.begin(), x.end());
}
// 将 i 所指元素接合于 position 所指位置之前
// position 和i 可指向同一个list。
void splice(iterator position, list&, iterator i)
{
iterator j = i;
++j;
if (position == i || position == j) return;
transfer(position, i, j);
}
// 将 [first,last) 内的所有元素接合于 position 所指位置之前
// position 和[first,last)可指向同一个list
// 但position不能位于[first,last)之内
void splice(iterator position, list&, iterator first, iterator last)
{
if (first != last)
transfer(position, first, last);
}
void remove(const _T& value);
void unique();
void merge(list& x);
void reverse();
void sort();
template <class _Predicate> void remove_if(_Predicate);
template <class _BinaryPredicate> void unique(_BinaryPredicate);
template <class _StrictWeakOrdering> void merge(list&, _StrictWeakOrdering);
template <class _StrictWeakOrdering> void sort(_StrictWeakOrdering);
friend bool operator==(const list& x, const list& y);
};
template <class _T, class _Alloc>
inline
bool operator==(const list<_T, _Alloc>& x, const list<_T, _Alloc>& y)
{
typedef typename list<_T, _Alloc>::link_type link_type;
link_type e1 = x.node;
link_type e2 = y.node;
link_type n1 = (link_type)e1->next;
link_type n2 = (link_type)e2->next;
for (; n1 != e1 && n2 != e2;
n1 = (link_type)n1->next, n2 = (link_type)n2->next)
if (n1->data != n2->data)
return false;
return n1 == e1 && n2 == e2;
}
template <class _T, class _Alloc>
inline bool operator<(const list<_T, _Alloc>& x, const list<_T, _Alloc>& y)
{
return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
template <class _T, class _Alloc>
inline void swap(list<_T, _Alloc>& x, list<_T, _Alloc>& y)
{
x.swap(y);
}
//insert实现
template <class _T, class _Alloc> template <class _InputIterator>
void list<_T, _Alloc>::insert(iterator position,
_InputIterator first, _InputIterator last)
{
for (; first != last; ++first)
insert(position, *first);
}
//insert实现
template <class _T, class _Alloc>
void list<_T, _Alloc>::insert(iterator position, size_type n, const _T& x)
{
for (; n > 0; --n)
insert(position, x);
}
//erase实现
template <class _T, class _Alloc>
typename list<_T, _Alloc>::iterator list<_T, _Alloc>::erase(iterator first, iterator last)
{
while (first != last) erase(first++);
return last;
}
//resize实现
template <class _T, class _Alloc>
void list<_T, _Alloc>::resize(size_type new_size, const _T& x)
{
iterator i = begin();
size_type len = 0;
for (; i != end() && len < new_size; ++i, ++len)
;
if (len == new_size)
erase(i, end());
else // i == end()
insert(end(), new_size - len, x);
}
// 清除所有节点(整个链表)
template <class _T, class _Alloc>
void list<_T, _Alloc>::clear()
{
link_type cur = (link_type)node->next; // begin()
while (cur != node)
{ // 巡访每一个节点
link_type tmp = cur;
cur = (link_type)cur->next;
destroy_node(tmp); // 摧毁(解构并释放)一个节点
}
// 恢复 node 原始状态
node->next = node;
node->prev = node;
}
template <class _T, class _Alloc>
list<_T, _Alloc>& list<_T, _Alloc>::operator=(const list<_T, _Alloc>& rhs)
{
if (this != &rhs) //不是自赋值
{
iterator first1 = begin();
iterator last1 = end();
const_iterator first2 = rhs.begin();
const_iterator last2 = rhs.end();
while (first1 != last1 && first2 != last2) *first1++ = *first2++;
if (first2 == last2) //右边链表较短
erase(first1, last1); //清除左边多余节点
else //左边链表较短
insert(last1, first2, last2); //插入右边多出的节点
}
return *this;
}
// 将数值为 value 之所有元素移除
template <class _T, class _Alloc>
void list<_T, _Alloc>::remove(const _T& value)
{
iterator first = begin();
iterator last = end();
while (first != last)
{ // 巡访每一个节点
iterator next = first;
++next;
if (*first == value) erase(first); // 找到就移除
first = next;
}
}
// 移除数值相同的连续元素
template <class _T, class _Alloc>
void list<_T, _Alloc>::unique()
{
iterator first = begin();
iterator last = end();
if (first == last) return;
iterator next = first;
while (++next != last)
{
if (*first == *next)
erase(next);
else
first = next;
next = first;
}
}
// 将 x 合并到 *this 身上。两个 lists 的内容都必须先经过升序。
template <class _T, class _Alloc>
void list<_T, _Alloc>::merge(list<_T, _Alloc>& x)
{
iterator first1 = begin();
iterator last1 = end();
iterator first2 = x.begin();
iterator last2 = x.end();
// 注意:前提是,两个 lists 都已经过升序,
while (first1 != last1 && first2 != last2)
if (*first2 < *first1)
{
iterator next = first2;
transfer(first1, first2, ++next);
first2 = next;
}
else
++first1;
if (first2 != last2) transfer(last1, first2, last2);
}
// 将 *this 的内容逆向重置
template <class _T, class _Alloc>
void list<_T, _Alloc>::reverse()
{
// 以下判断,如果是空白串行,或仅有一个元素,就不做任何动作。
// 使用 size() == 0 || size() == 1 来判断,虽然也可以,但是比较慢。
if (node->next == node || link_type(node->next)->next == node) return;
iterator first = begin();
++first;
while (first != end()) {
iterator old = first;
++first;
transfer(begin(), old, first);
}
}
// list 不能使用算法sort(),必须使用自己的sort() member function,
// 因为算法sort()只接受RamdonAccessIterator.
// 本函数采用 quick sort.
template <class _T, class _Alloc>
void list<_T, _Alloc>::sort()
{
// 以下判断,如果是空链表,或仅有一个元素,就不做任何动作。
if (node->next == node || link_type(node->next)->next == node) return;
// 一些新的 lists,做为中介数据存放区
list<_T, _Alloc> carry;
list<_T, _Alloc> counter[64];
int fill = 0;
while (!empty())
{
carry.splice(carry.begin(), *this, begin());
int i = 0;
while (i < fill && !counter[i].empty())
{
counter[i].merge(carry);
carry.swap(counter[i++]);
}
carry.swap(counter[i]);
if (i == fill) ++fill;
}
for (int i = 1; i < fill; ++i)
counter[i].merge(counter[i - 1]);
swap(counter[fill - 1]);
}
template <class _T, class _Alloc> template <class _Predicate>
void list<_T, _Alloc>::remove_if(_Predicate pred)
{
iterator first = begin();
iterator last = end();
while (first != last) {
iterator next = first;
++next;
if (pred(*first)) erase(first);
first = next;
}
}
template <class _T, class _Alloc> template <class _BinaryPredicate>
void list<_T, _Alloc>::unique(_BinaryPredicate binary_pred) {
iterator first = begin();
iterator last = end();
if (first == last) return;
iterator next = first;
while (++next != last) {
if (binary_pred(*first, *next))
erase(next);
else
first = next;
next = first;
}
}
template <class _T, class _Alloc> template <class _StrictWeakOrdering>
void list<_T, _Alloc>::merge(list<_T, _Alloc>& x, _StrictWeakOrdering comp)
{
iterator first1 = begin();
iterator last1 = end();
iterator first2 = x.begin();
iterator last2 = x.end();
while (first1 != last1 && first2 != last2)
if (comp(*first2, *first1)) {
iterator next = first2;
transfer(first1, first2, ++next);
first2 = next;
}
else
++first1;
if (first2 != last2) transfer(last1, first2, last2);
}
template <class _T, class _Alloc> template <class _StrictWeakOrdering>
void list<_T, _Alloc>::sort(_StrictWeakOrdering comp) {
if (node->next == node || link_type(node->next)->next == node) return;
list<_T, _Alloc> carry;
list<_T, _Alloc> counter[64];
int fill = 0;
while (!empty()) {
carry.splice(carry.begin(), *this, begin());
int i = 0;
while (i < fill && !counter[i].empty()) {
counter[i].merge(carry, comp);
carry.swap(counter[i++]);
}
carry.swap(counter[i]);
if (i == fill) ++fill;
}
for (int i = 1; i < fill; ++i) counter[i].merge(counter[i - 1], comp);
swap(counter[fill - 1]);
}
}//end of MySTL
#endif//end of LIST_H

浙公网安备 33010602011771号