这里写目录标题
什么是list
双向循环链表
list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代
与其他序列式容器相比,list和forward_list最大的缺陷式不支持任意位置的随机访问,比如:要访问list的第三个元素,必须从头节点或尾结点开始遍历,同时,list还需要一些额外的空间,以保存每个节点的相关联信息(对于储存类型较小元素的大list来说这可能式一个重要的因素)
list模拟实现整体思路
两个迭代器在物理层面上是相同的,都是指向一个地址,且在32位下大小都是四个字节,但是他们的类型是不同的,vector的迭代器就是内置类型,无论是前置++还是后置++都是c++中自带的,但是list的迭代器是我们自定义的,为了让list在最上层使用的感觉和其他容器一样,我们必须重载list的迭代器!
为什么template<class T,class Ref,class Ptr> 三个参数
运算符->
Ptr operator->()
{
return &_node->_data;
}
返回值是迭代器的指针
vector与list比较
Stl_list整体实现
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<assert.h>
namespace zjt
{
template<class T>
struct list_node
{
list_node<T>* _next;
list_node<T>* _prev;
T _data;
list_node(const T& val = T())
:_next(nullptr)
, _prev(nullptr)
, _data(val)
{}
};
//由于list的每一个元素类型都是自定义的,为了使迭代器在
//最上层使用的效果和其他容器一样,我们必须要将迭代器定义成自定义类型
//并且使其运算符重载
template<class T,class Ref,class Ptr>//Ref--(const)T& Ptr--(const)T*
struct _list_iterator
{
typedef list_node<T> Node;
typedef _list_iterator<T, Ref, Ptr> self;
Node* _node;//主体是指向结点的指针
_list_iterator(Node*node)
:_node(node)
{}
//析构函数 ——结点不属于迭代器,不需要迭代器释放
//拷贝构造和赋值重载——默认生成的浅拷贝即可
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
self& operator++()//前置++
{
_node = _node->_next;
return *this;
}
self operator++(int)//后置++
{
self tmp(_node);
_node = _node->_next;
return tmp;//tmp此时出了作用域就会还给操作系统,所以不能用引用返回
}
self operator--()
{
_node = _node->_prev;
return *this;
}
self operator--(int)
{
self tmp(_node);
_node = _node->_prev;
return tmp;
}
bool operator==(const self& it)
{
return _node == it._node;
}
bool operator!=(const self& it)
{
return _node != it._node;
}
};
template<class T>
class list
{
typedef list_node<T>Node;
public:
typedef _list_iterator<T, T&, T*> iterator;
typedef _list_iterator<T, const T&, const T*> const_iterator;
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);
}
list()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
}
void empty_init()
{
_head = new Node();
_head->_next = _head;
_head->_prev = _head;
}
template<class InputIterator>
list(InputIterator first, InputIterator last)
{
empty_init();
while (first != last)
{
push_back(*first);
first++;
}
}
void swap(list<T>& it)
{
std::swap(_head, it._head);
}
//拷贝构造现代写法
list(const list<T>& it)
{
empty_init();
list<T>tam(it.begin().it.end());
swap(tam);
}
void push_back(const T& x)
{
Node* tail = _head->_prev;
Node* newnode = new Node(x);
// _head tail newnode
tail->_next = newnode;
newnode->_prev = tail;
newnode->_next = _head;
_head->_prev = newnode;
}
list<T>& operator=(list<T>it)
{
swap(it);
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
}
void push_front(const T& x)
{
insert(begin(), x);
}
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
iterator erase(iterator pos)
{
assert(pos != end());
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
//prev next
prev->_next = next;
next->_prev = prev;
delete cur;
return iterator(next);//返回删除元素的下一个位置
}
iterator insert(iterator pos,const T&x)
{
Node* newnode = new Node(x);
Node* cur = pos._node;
Node* prev = cur->_prev;
//prev newnode cur
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
}
private:
Node* _head;//哨兵位的头结点
};
}