前言
- 本质:双向带头循环链表
- 实现list(双向带头循环链表)模板需要:
- 单个节点的类模板,包含成员变量的声明,和初始化
- 迭代器模板:成为单个节点类型的指针;成员变量的声明,初始化;成员函数++、!=、*迭代器类型对象
节点模板、迭代器模板
- clear清理到只剩最后一个头节点即可。
namespace mylist
{
template<class T>
struct _list_node
{
_list_node<T>* _next;
_list_node<T>* _prev;
T _data; /数据
_list_node(const T& x = T())
:_next(nullptr)
, _prev(nullptr)
, _data(x)
};
template<class T>
struct _list_itreator
{
typedef _list_node<T> Node;
Node* _node;
_list_itreator(Node* _node)
:_node(node)
{}
T& operator*()
{
return _node->_data;
}
// ++it
_list_itreator<T>& operator++()
{
_node = _node->_next;
return *this;
}
bool operator!=(const _list_itreator<T>& it)
{
return _node != it._node;
}
};
}
list模板
重载->
it->->
it 调用-> 再去访问->second 编译器就优化了it->second
重载 *
- 返回的是数据的引用
T& operator*()
{
return this->_data;
}
容器的交换
- 用容器内部的成员函数
.sawp()
,交换的是头指针的值。 - 库里面的是深拷贝,申请内存,效率太慢。
迭代器:单向,双向,随机,const
- 单向:只能++,不能–;链表
- 双向:可以++,也可以–;双向链表,map
- 随机:可以++,可以–,可以+,可以-;底层是数祖的,string/vector/deque/map
- 迭代器的本质是内置类型的指针拷贝构造和赋值重载会完成值浅拷贝。
- 迭代器是算法和容器之间的胶合剂,对让算法对所有容器都有统一的访问方式。
总结
对于一个迭代器类型 T,我们会关心和它相关的如下信息:
- 它是哪种类型的迭代器;
- 它指向的数据类型是什么;
- 这个数据类型的引用类型是什么;
- 这个数据类型的指针类型是什么;
- 两个迭代器的距离用什么类型表示。