您的位置:首页 > 理论基础 > 数据结构算法

剖析容器List

2017-07-19 13:11 78 查看

List

零个或者多个数据元素的有限序列;

A. 是一个序列:元素之间有顺序,每一个元素都有前驱和后继;(这里的链表是一个带头节点的双向循环链表)



B. 有限的;

综上所述:ListNode的模型如下:



迭代器:一种遍历容器的方式,只作遍历,修改的作用,不析构节点;分为:普通迭代器(可读可改),const迭代器(可读不可改),反向迭代器(反向遍历);

模拟实现正向迭代器基本功能,代码如下:



template <class T>
struct _ListNode
{
T _data;
ListNode<T>* _prev;
ListNode<T>* _next;

_ListNode(const T& data)
:_data(data),_prev(NULL),_next(NULL)
{}

T& operator*()
{
return _data;
}
};

template <class T, class Ref, class Ptr>
struct _ListIterator
{
typedef _ListNode<T> Node;
typedef _ListIterator<T,Ref,Ptr> Self;
Node* _node;

_ListIterator(Node* node)
:_node(node)
{}

Self& operator++()//前置++
{
_node = _node->_next;
return *this;
}
Self operator++(int)//后置++
{
Self* cur(_node);
_node = _node->_next;
return cur;
}
Self& operator--()//前置--
{
_node = _node->_prev;
return *this;
}
Self operator--(int)//后置--
{
Self cur(_node);
_node = _node->_prev;
return cur;
}

Ref operator*()//Ref == T&
{
return _node->_data;
}
Ptr operator->()//返回了一个指针,其实就是如何将一个迭代器转化成一个指针,使其具有指针变量的属性
{
return &_node->_data;//返回了这个数的地址,将其赋给一个指针变量
}

bool operator!=(const Self& t) const
{
return _node != t._node;
}
};
//具有头节点的双向循环链表
template <class T>
class _List
{
typedef _ListNode<T> Node;
typedef _ListIterator<T,T&,T*> Iterator;
typedef _ListIterator<T,const T&,const T*> IteratorConst;
protected:
Node* _head;
public:
Node* GetNode(const T& data)//这里表示让一个指针指向一个空间
{
return new Node(data);
}
_List()//这是一个含有头节点的双向链表,所以头节点也应该有空间,里面的存放的数据可以设置为默认值
{
_head = GetNode(T());//根据类型确定默认值
_head->_next = _head;
_head->_prev = _head;
}

~_List()
{
_clear();
/*clear_Iterator();*/
delete _head;//头节点有空间必须要析构
_head = NULL;
}

//普通的迭代器
Iterator Begin()
{
return Iterator(_head->_next);
}
Iterator End()
{
return Iterator(_head);
}

//const迭代器
IteratorConst Begin() const
{
return IteratorConst(_head->_next);
}
IteratorConst End() const
{
return IteratorConst(_head);
}

//没有使用迭代器以前
Node* Find(const T& data)
{
Node* cur = _head->_next;
while(cur != _head)
{
if(*cur == data)
return cur;
cur = cur->_next;
}
return _head;
}
//使用迭代器以后
Iterator Find(const T& data)
{
Iterator it = Begin();
while(it != End())
{
if(*it == data)
return it;
++it;
}
return it;
}

//没有使用迭代器之前
void _clear()
{
Node* cur = _head->_next;
while(cur != _head)
{
Node* del = cur;
cur = cur->_next;
delete del;
}
_head->_next = _head;
_head->_prev = _head;
}
//使用迭代器以后
void clear_Iterator()
{
Iterator cur = Begin();
while(cur != End())
{
Node* del = cur._node;
++cur;
delete del;
}
_head->_next = _head;
_head->_prev = _head;
}

// 设计一个双向链表,实现随机位置的插入和删除,在pos的前面进行插入
void Insert(const Node* pos,const T& data)
{
assert(pos);
Node* cur = GetNode(data);
Node* pre = pos->_prev;
pre->_next = cur;
cur->_prev = pre;
cur->_next = pos;
pos->_prev = cur;
}
void Insert(Iterator pos, const T& data)
{
assert(pos._node);
Node* cur = GetNode(data);
Iterator pr = --pos;
pr._node->_next = cur;
cur->_prev = pr._node;
cur->_next = pos._node;
pos._node->_prev = cur;
}

Iterator Erase(Iterator& pos)//删除
{
assert(pos._node && pos == End());//_node不能为NULL,且不能删除_head节点
Iterator pre = --pos;
Iterator nex = ++pos;
pre._node->_next = nex._node;
nex._node->_prev = pre._node;

delete pos._node;
pos = pre;
return nex;
}

void PopFront()//头删
{
Erase(Begin());
}
void PopBack()//尾删
{
Erase(--End());
}
void PushFront(const T& data)//头插
{
Insert(Begin(),data);
}
void PushBack(const T& data)//尾插
{
Insert(End(),data);
}

bool IsEmpty()
{
return _head == _head->_next;
}

//模板内的成员函数也可以设计成模板函数
template <class InputIterator>
//将某个对象区间内的值拷贝到当前对象中
void Assign(InputIterator first,InputIterator last)//[)左闭右开的区间
{
_clear();//先清空再拷贝
while(first != last)
{
pubshBack(*first);//first进行*引用就取到了里面的data值了
++first;
}
}
};


3.迭代器失效问题:



4.反向迭代器:



不管是正向迭代器还是反向迭代器,在遍历我们的list中的元素时都是要从begin()所指向的那个节点开始的,然后一个一个往下执行,直到发现当前所指向的那个节点 == end()而结束;

对于反向迭代器而言,我们用begin()开始进行遍历的时候都是访问的是它所指向的下一个节点,在这里可能就比较绕了。这里的下一个节点我们使用”- -“的方式进行访问,那么你一定有疑问了,看图之后“- -”,那么就直接 == end()了,那么遍历才刚开始就结束了吗?当然不是,这里我们要注意,我们的下一个节点是针对正向迭代器而言的,正向迭代器的“- -”,就是反向迭代器的“++”。



代码如下:

充分利用正向迭代器进行函数的复用;

//反向迭代器:
template <class Iterator>
class ReverIterator
{
protected:
Iterator _current;
typedef ReverIterator<Iterator> Self;
public:
ReverIterator(Iterator cur)
:_current(cur)
{}

Self& operator++()//前置++
{
--_current;//运用正向迭代器的--就是反向迭代器的++
return *this;
}
Self operator++(int)//后置++
{
ReverIterator re(_current);
--_current;
return re;
}
Self& operator--()//前置--
{
++_current;
return *this;
}
Self operator--(int)//后置--
{
ReverIteratr cur(_current);
++_current;
return cur;
}
//typename的意思是强调后面修饰的这个是一个类型,模板类的内嵌类型,用typename强调
typename Iterator::Reference operator*()
{
Iterator cur = _current;
return *(--cur);//访问当前指向的下一个值
}
typename Iterator::Pointer operator->()
{
return &operator*();
}

bool operator!=(const Self& cur)
{
return _current != cur._current;
}

};


list中增添以下代码:

typedef ReverIterator<Iterator> ReIterator;
typedef ReverIterator<IteratorConst> ReIteratorConst;

ReIterator RBegin()
{
return ReIterator(End());
}
ReIterator REnd()
{
return ReIterator(Begin());
}
ReIteratorConst RBegin() const
{
return ReIteratorConst(End());
}
ReIteratorConst REnd() const
{
return ReIteratorConst(Begin());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 迭代器