1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。
5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)
下面是源码: 这是没有按照库里面实现的, 所以迭代器类写了两个
一个是供给可读可写的list对象, 一个是供给只读不可写的list对象
#include
using namespace std;
//节点结构体类
template <class T>
struct ListNode
{
T _data;
ListNode<T>* _prev;
ListNode<T>* _next;
ListNode(const T& value = T())
:_data(value)
, _prev(nullptr)
, _next(nullptr)
{
}
};
//迭代器类实现 - 可读可写
template <class T>
struct ListIterator
{
typedef ListNode<T> Node;
typedef ListNode<T>* pNode;
typedef ListIterator<T> Self;
pNode _node;
ListIterator(pNode node)
:_node(node)
{
}
//解引用: 可读可写
T& operator*()
{
return _node->_data;
}
// ptr->_year; 可以可写
T* operator->()
{
return &operator*();
//return &_node->_data;
}
//迭代器前置++
Self& operator++()
{
_node = _node->_next;
return *this;
}
//迭代器后置加加
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
//!=
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
//return !*this != it;
}
};
//迭代器类实现二 - 可读不可写
template <class T>
struct ListConstIterator
{
typedef ListNode<T> Node;
typedef ListNode<T>* pNode;
typedef ListConstIterator<T> Self;
pNode _node;
ListConstIterator(pNode node)
:_node(node)
{
}
//解引用: 只读
const T& operator*()
{
return _node->_data;
}
// ptr->_year; 只读
const T* operator->()
{
return &operator*();
//return &_node->_data;
}
//迭代器前置++
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
//!=
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
//return !*this != it;
}
};
//模拟实现List类
template<class T>
class List {
public:
typedef ListNode<T> Node;
typedef Node* pNode;
typedef ListIterator<T> iterator;
typedef ListConstIterator<T> const_iterator;
//构造函数
List()
:_Head(new Node)
{
//首先先要自环, 很关键
_Head->_next = _Head;
_Head->_prev = _Head;
}
//迭代器构造函数
template<class Inputiterator>
List(Inputiterator begin, Inputiterator end)
:_Head(new Node)
{
_Head->_next = _Head;
_Head->_prev = _Head;
while (begin != end) {
Pushback(*begin);
++begin;
}
}
//构造函数 -- 必须要深拷贝
List(const List<T>& lst)
:_Head(new Node)
{
_Head->_next = _Head;
_Head->_prev = _Head;
for (auto it : lst) {
Pushback(it); //Insert也可以
}
}
//赋值运算符重载 - 现在写法
List<T>& operator=(List<T>& lst) {
swap(_Head, lst._Head);
return *this;
}
//析构函数
~List() {
Clear();
if (_Head) {
delete _Head;
_Head = nullptr;
}
}
//尾插元素
void Pushback(const T& val) {
pNode prev_Node = _Head->_prev; //得到尾节点
pNode newNode = new Node(val);
prev_Node->_next = newNode;
newNode->_prev = prev_Node;
newNode->_next = _Head;
_Head->_prev = newNode;
//下面是两种不同的写法, 代码复用
//Insert(iterator(_Head), val);
//INsert(end(), val);
}
//头插元素
void PushFront(const T& val) {
pNode next_Node = _Head->_next;
pNode newNode = new Node(val);
_Head->_next = newNode;
newNode->_prev = _Head;
newNode->_next = next_Node;
next_Node->_prev = newNode;
//Insert(iterator(_Head->_next), val);
//Insert(begin(), val);
}
//头删
void PopFront() {
//方法实现和头插一样, 不重点写
Erase(begin());
}
//尾删
void Popback() {
Erase(--end());
}
//任意位置插入 - 传入的迭代器和值
void Insert(iterator pos, const T& val) {
//在迭代器的位置插入 -- 迭代器是一个类
pNode node = pos._node;
//先得到Node前面的节点
pNode prev = node->_prev;
pNode newNode = new Node(val);
prev->_next = newNode;
newNode->_prev = prev;
newNode->_next = node;
node->_prev = newNode;
}
//任意位置删除
iterator Erase(iterator pos) {
//在这块头节点_Head是不能删除的
if (pos._node != _Head) {
pNode node = pos._node;
pNode prev = node->_prev;
prev->_next = node->_next;
node->_next->_prev = prev;
++pos;
}
return pos;
}
//判空函数
bool Empty() {
if (_Head->_next == _Head)
return true;
else
return false;
}
//清理函数
void Clear() {
if (!Empty()) {
pNode cur = _Head->_next;
while (cur != _Head) {
pNode next = cur->_next;
delete cur;
cur = next;
}
//因此_Head不是在堆上开辟的, 因此不需要释放, 但是自环操作一定要有, 作为一些为空等一些接口的判断依据。
_Head->_next = _Head;
_Head->_prev = _Head;
}
//写法2
//if (!Empty()) {
// iterator it = begin();
// while (it != end()) {
// Erase(it);
// }
//}
}
//容器大小or长度
size_t Size() {
size_t count = 0;
pNode tmp = _Head->_next;
while(tmp != _Head)
{
++count;
tmp = tmp->_next;
}
return count;
}
//下面是迭代器接口
iterator begin() {
return iterator(_Head->_next);
}
iterator end() {
return iterator(_Head);
}
const_iterator begin() const {
return const_iterator(_Head->_next);
}
const_iterator end() const {
return const_iterator(_Head);
}
private:
pNode _Head;
};
下面是借鉴库里面实现list容器方法写的 - 就是在迭代器类模板进行修改。
我们知道const 实例化的list对象和 非const 实例化list对象关键就在于修改权限,
非const实例化的list对象在使用迭代器时是需要迭代器提供可读可写的, const修饰则不相同, 因此const修饰的无法调动正常的迭代器, 因此权限可以缩小但是不能放大, 所以会多写一个特殊的可读不可写的迭代器类, 库里面实现的方法巧妙地解决了这个问题, 使得了一个迭代器类就可以搞定 - 下面代码请欣赏!
关于迭代器问题, 也是在这块体现出来, 为什么vector, string可以不写迭代器类就可以完成迭代器的功能, 但是list不行呢? 需要手动实现, 这是一个值得思考总结的问题。
#include
using namespace std;
template <class T>
struct ListNode
{
T _data;
ListNode<T>* _prev;
ListNode<T>* _next;
ListNode(const T& value = T())
:_data(value)
, _prev(nullptr)
, _next(nullptr)
{
}
};
/*区别一*/
//迭代器实现 - 既可以做到可读可写, 又可以做到可读不可写!
template <class T, class Ref, class Ptr>
struct ListIterator
{
typedef ListNode<T> Node;
typedef ListNode<T>* pNode;
typedef ListIterator<T, Ref, Ptr> Self;
pNode _node;
ListIterator(pNode node)
:_node(node)
{
}
//解引用: 可读可写
Ref operator*()
{
return _node->_data;
}
// ptr->_year; 可以可写
Ptr operator->()
{
return &operator*();
//return &_node->_data;
}
//迭代器前置++
Self& operator++()
{
_node = _node->_next;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_node = _node->_next;
return tmp;
}
Self& operator--()
{
_node = _node->_prev;
return *this;
}
Self operator--(int)
{
Self tmp(*this);
_node = _node->_prev;
return tmp;
}
//!=
bool operator!=(const Self& it)
{
return _node != it._node;
}
bool operator==(const Self& it)
{
return _node == it._node;
//return !*this != it;
}
};
template<class T>
class List {
public:
typedef ListNode<T> Node;
typedef Node* pNode;
/*区别2*/
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
List()
:_Head(new Node)
{
//首先先要自环, 很关键
_Head->_next = _Head;
_Head->_prev = _Head;
}
//迭代器构造函数
template<class Inputiterator>
List(Inputiterator begin, Inputiterator end)
:_Head(new Node)
{
_Head->_next = _Head;
_Head->_prev = _Head;
while (begin != end) {
Pushback(*begin);
++begin;
}
}
//构造函数 -- 必须要深拷贝
List(const List<T>& lst)
:_Head(new Node)
{
_Head->_next = _Head;
_Head->_prev = _Head;
for (auto it : lst) {
Pushback(it); //Insert也可以
}
}
//赋值运算符重载 - 现在写法
List<T>& operator=(List<T>& lst) {
swap(_Head, lst._Head);
return *this;
}
~List() {
Clear();
if (_Head) {
delete _Head;
_Head = nullptr;
}
}
//尾插元素
void Pushback(const T& val) {
pNode prev_Node = _Head->_prev; //得到尾节点
pNode newNode = new Node(val);
prev_Node->_next = newNode;
newNode->_prev = prev_Node;
newNode->_next = _Head;
_Head->_prev = newNode;
//Insert(iterator(_Head), val);
//INsert(end(), val);
}
//头插元素
void PushFront(const T& val) {
pNode next_Node = _Head->_next;
pNode newNode = new Node(val);
_Head->_next = newNode;
newNode->_prev = _Head;
newNode->_next = next_Node;
next_Node->_prev = newNode;
//Insert(iterator(_Head->_next), val);
//Insert(begin(), val);
}
//头删
void PopFront() {
//方法实现和头插一样, 不重点写
Erase(begin());
}
void Popback() {
Erase(--end());
}
//任意位置插入
void Insert(iterator pos, const T& val) {
//在迭代器的位置插入 -- 迭代器是一个类
pNode node = pos._node;
//先得到Node前面的节点
pNode prev = node->_prev;
pNode newNode = new Node(val);
prev->_next = newNode;
newNode->_prev = prev;
newNode->_next = node;
node->_prev = newNode;
}
//删除任意迭代器位置的
iterator Erase(iterator pos) {
//在这块头节点_Head是不能删除的
if (pos._node != _Head) {
pNode node = pos._node;
pNode prev = node->_prev;
prev->_next = node->_next;
node->_next->_prev = prev;
++pos;
}
return pos;
}
bool Empty() {
if (_Head->_next == _Head)
return true;
else
return false;
}
void Clear() {
//清理函数
if (!Empty()) {
pNode cur = _Head->_next;
while (cur != _Head) {
pNode next = cur->_next;
delete cur;
cur = next;
}
//因此_Head不是在堆上开辟的, 因此不需要释放, 但是自环操作一定要有, 作为一些为空等一些接口的判断依据。
_Head->_next = _Head;
_Head->_prev = _Head;
}
//写法2
//if (!Empty()) {
// iterator it = begin();
// while (it != end()) {
// Erase(it);
// }
//}
}
size_t Size() {
size_t count = 0;
pNode tmp = _Head->_next;
while(tmp != _Head)
{
++count;
tmp = tmp->_next;
}
return count;
}
iterator begin() {
return iterator(_Head->_next);
}
iterator end() {
return iterator(_Head);
}
const_iterator begin() const {
return const_iterator(_Head->_next);
}
const_iterator end() const {
return const_iterator(_Head);
}
private:
pNode _Head;
};
能力有限, 很多接口考虑不到, 请多多包涵! - 祝各位新年快乐!