实现一个单链表,或是双向链表,是我们学习、面试,和工作中经常遇到的问题,于是,我们这里动手实现一个双向循环链表。
在上一篇,我们在原有的std::list基础上,扩展了增删改查等一系列接口。为适用于普通算法,这里实现了迭代器的功能。为防止重复申请和释放操作,内部保留一个已分配的空间,以提高性能。
本文源码见【完整代码】章节,或GitHub:https://github.com/deargo/cpphelper。
实现介绍
链表的接口完全参考std::list,但为了实际使用,需要加以丰富,比如新增、查询、删除、检索、排序、去重等。
链表可迭代器访问,支持前向和反向迭代器,以便于适用于算法函数。
为提高链表性能,减少频繁的新增和删除元素,内部使用两个链式结构。其中用于存储数据的链表,为双向链表;用于分配内存的链表为单向链表。
两个链表中的每个元素,都继承自NodeBase,他包含前驱指针prev,和后继指针next。
存储链表元素为Node结点,他的唯一成员为存储的数据对象。但比较特殊都是,其哨兵结点为NodeBae类型。保留链表为提高性能,存储为NodeBase对象,且作为单向列表,取值和新增,都在头结点操作。
内部链表结构见下图:
完整代码
#pragma once
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
#include <list>
#include <vector>
#include <set>
#include <algorithm>
#include <functional>
#include <assert.h>
namespace CppHelper
{
template<typename Type>
class CLinkList
{
private:
//定义双链表的前驱结点和后继节点
struct NodeBase
{
NodeBase* next;
NodeBase* prev;
NodeBase() : next(nullptr), prev(nullptr) {}
};
//仅定义数据成员,将数据操作和链表操作分离
struct Node : public NodeBase
{
Type data;
};
private:
//双向迭代器前置声明
class Iterator;
//const双向迭代器
class ConstIterator
{
friend class CLinkList;
const NodeBase* node = nullptr;
const NodeBase* guard = nullptr;
ConstIterator(const NodeBase *pGuard, const NodeBase *pNode) : guard(pGuard),node(pNode) {}
public:
typedef ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
typedef Type value_type;
typedef const Type* pointer;
typedef const Type& reference;
public:
ConstIterator(const Iterator& it) : guard(it.guard),node(it.node) {}
reference operator*() const { assert(guard!=node); return static_cast<const Node*>(node)->data; }
pointer operator->() const { assert(guard!=node); return &static_cast<const Node*>(node)->data; }
ConstIterator& operator++() { node = node->next; return *this; }
ConstIterator operator++(int) { const ConstIterator temp = *this; node = node->next; return temp; }
ConstIterator& operator--() { node = node->prev; return *this; }
ConstIterator operator--(int) { const ConstIterator temp = *this; node = node->prev; return temp; }
ConstIterator operator+(int distance) const
{
ConstIterator temp = *this;
while(temp.node && distance--) temp.node = temp.node->next;
return temp;
}
ConstIterator operator-(int distance) const
{
ConstIterator temp = *this;
while(temp.node->prev && distance--) temp.node = temp.node->prev;
return temp;
}
ConstIterator& operator+=(int distance) { while(node && distance--) node = node->next; return *this; }
ConstIterator& operator-=(int distance) { while(node->prev && distance--) node = node->prev;return *this;}
bool operator==(const ConstIterator& other) const { return node == other.node; }
bool operator!=(const ConstIterator& other) const { return node != other.node; }
bool valid() const { return guard!=node;}
};
//双向迭代器
class Iterator
{
friend class CLinkList;
NodeBase* node = nullptr;
const NodeBase* guard = nullptr;
Iterator(NodeBase* pGuard, NodeBase* pNode) : guard(pGuard),node(pNode){}
public:
typedef ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
typedef Type value_type;
typedef Type* pointer;
typedef const Type* const_pointer;
typedef Type& reference;
typedef const Type& const_reference;
public:
reference operator*() { assert(guard!=node); return static_cast<Node*>(node)->data; }
const_reference operator*() const { assert(guard!=node); return static_cast<Node*>(node)->data; }
pointer operator->() { assert(guard!=node); return &static_cast<Node*>(node)->data; }
const_pointer operator->() const { assert(guard!=node); return &static_cast<Node*>(node)->data; }
Iterator& operator++() { node = node->next; return *this; }
Iterator operator++(int) { Iterator temp = *this; node = node->next; return temp; }
Iterator& operator--() { node = node->prev; return *this; }
Iterator operator--(int) { Iterator temp = *this; node = node->prev; return temp; }
Iterator operator+(int distance)
{
Iterator temp = *this;
while(temp.node && distance--) temp.node = temp.node->next;
return temp;
}
ConstIterator operator+(int distance) const
{
Iterator temp = *this;
while(temp.node && distance--) temp.node = temp.node->next;
return ConstIterator(temp.node);
}
Iterator operator-(unsigned int distance)
{
Iterator temp = *this;
while(temp.node->prev && distance--) temp.node = temp.node->prev;
return temp;
}
ConstIterator operator-(unsigned int distance) const
{
Iterator temp = *this;
while(temp.node->prev && distance--) temp.node = temp.node->prev;
return ConstIterator(temp.node);
}
Iterator& operator+=(unsigned int distance) { while(node && distance--) node = node->next; return *this; }
Iterator& operator-=(unsigned int distance) { while(node->prev && distance--) node = node->prev; return *this; }
bool operator==(const Iterator& other) const { return node == other.node; }
bool operator!=(const Iterator& other) const { return node != other.node; }
bool valid() const{ return guard!=node;}
};
public:
typedef Type value_type;
typedef Typ