文章目录
1.list用法
1.1list介绍
1.list是带头的双向循环链表,支持在任意位置的插入和删除,可以前后双向迭代
forward_list为单向链表,只支持往前迭代,不支持往后迭代
2.list的插入效率比vector效率要高,因为不需要数据的移动
3.list的缺陷是不支持数据的随机访问,因此,插入删除频繁的选用list,而需要随机访问的选择vector
4.list的插入删除都是在当前位置进行,插入元素返回插入的节点的指针,删除节点则是返回节点删除前的下一个位置的节点的指针
forward_list则只支持在单前位置的后面插入和删除元素
1.2 list iterator
beigin和end分别返回第一个元素和最后一个元素的下一个位置的迭代器
rbeng和rend返回反向迭代器,即返回最后一个元素的反向迭代器和第一个元素的前一个元素的反向迭代器(reverse_iterator)
1.3 list capacity
empty:检测list是否为空,是返回true,否返回false
size:返回list之中有效节点的个数
1.4 list element access
front:返回list第一个节点值的引用
back:返回list最后一个节点值的引用
1.5 list modifiers
push_front:头插
pop_front:头删
push_back:尾插
pop_back:尾删
insert:在pos位置插入节点,返回插入节点的迭代器
erase:删除pos位置的节点,返回删除前下一个节点的迭代器
swap:交换两个list中的元素
clear:清空list中有效元素
2.list迭代器失效问题
list进行插入时,迭代器是不会失效的,因为没有开辟新的空间,严格意义上来讲迭代器也失效了,因为迭代器的含义发生了改变
而进行删除时会发生失效,因为pos迭代器位置被删除了,对应的迭代器自然失效了
3.list的模拟实现
1.链表是由一个个节点链接而成,因此首先需要构造一个节点类
2.链表的存储不是连续线性的物理空间,而是逻辑上的线性表。因此,迭代器不能是原生指针,而应该构造一个迭代器类,又迭代器和原生指针的用法是一致的,所以迭代器类中的方法实现需要包含以下几点:
a.指针是可以解引用的,因此需要重载operator *()
b.指针可以通过->访问其所指向的空间成员,因此需要重载operator ->()
c.指针可以 ++ --因此需要对前\后置自增自减进行重载,而单向链表forward_list不能往后走,因此不需要重载–,即list支持双向迭代器,forward_list支持单向迭代器,string,vector支持随机迭代器(iterator+n),list随机迭代器效率不高,因此不提供随机迭代器(由于不能提供随机迭代器,list就不能使用STL之中的排序,因为排序的底层是快排,需要三数取中,三数取中则需要随机迭代器的支持)
d.迭代器需要进行是否相等的比较,因此需要重载 operator ==()和operator !=()
3.1为什么需要三个模板参数
3.2抽象类迭代器
3.3代码实现
#pragma once
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <assert.h>
namespace my
{
//类节点
template<class T>
struct __list_node//用struct是因为全都是公有成员
{
__list_node(const T& data=T())//匿名对象,自动调用构造函数,构造一个节点
:_prev(nullptr)
, _next(nullptr)
, _data(data)
{}
__list_node<T> *_prev;
__list_node<T> *_next;
T _data;
};
//类迭代器 <T,T&,T*>
template<class T,class Ref,class Ptr>
struct __list_iterator//不是原生指针,所以要封装成类,重载运算符模拟原生指针的用法
{
typedef __list_node<T> node;
typedef struct __list_iterator<T,Ref,Ptr> self;//类型重定义
node *_node;//成员变量
//不需要拷贝,赋值,析构等等,编译器默认生成的就能用
__list_iterator(node *node)
:_node(node)
{
}
bool operator !=(const self &s)const
{
return (_node != s._node);
}
bool operator ==(const self &s)const
{
return (_node == s._node);
}
Ref operator *() const//返回的是引用的值,所以是Ref,反不反回const由模板决定
{
return _node->_data;
}
self &operator --()
{
_node = _node->_prev;
return *this;
}
self &operator ++()
{
_node = _node->_next;
return *this;
}
self operator --(int)
{
self rnode = _node;//隐式类型转换
_node = _node->_prev;
return rnode;
}
self operator ++(int)
{
self rnode = _node;//隐式类型转换
_node = _node->_next;
return rnode;
}
Ptr operator ->()const
{
return &_node->_data;
}
};
template<class T>
class list
{
public:
typedef __list_node<T> node;
typedef struct __list_iterator<T,T&,T*> iterator;
typedef struct __list_iterator<T, const T&, const T*> const_iterator;
public:
list()//初始化,双向循环链表头指向自己
{
_head = new node;
_head->_next = _head;
_head->_prev = _head;
}
template <class inputleterator>
list(inputleterator first, inputleterator last)
{
_head = new node;
_head->_next = _head;
_head->_prev = _head;
while (first != last)
{
push_back(*first);
++first;
}
}
list(const list<T>&ls)
{
_head = new node;//防止temp析构时崩掉
_head->_next = _head;
_head->_prev = _head;
/*const_iterator it = ls.begin();
while (it != ls.end())
{
push_back(*it);
++it;
}*/
list<T> temp(ls.begin(), ls.end());//构造一个临时对象
std::swap(_head, temp._head);//交换头节点
}
list<T> operator =(list<T> ls)//拷贝构造一份过来
{
std::swap(_head, ls._head);//直接交换两个头节点
return *this;
}
~list()
{
clear();
delete _head;
_head = nullptr;
}
//list iterator
iterator begin()
{
return _head->_next;//节点指针,隐式类型转换成迭代器
//等价于 return(_head->_next)//构造一下
//或者 iterator it(_head->_next),return it;
}
iterator end()
{
return _head;
}
const_iterator begin()const
{
return _head->_next;//节点指针,隐式类型转换成迭代器
//等价于 return(_head->_next)//构造一下
//或者 iterator it(_head->_next),return it;
}
const_iterator end()const
{
return _head;
}
//list capacity
bool empty()const
{
if (_head->_next == _head)
return true;
else
return false;
}
size_t size()const
{
const_iterator it = begin();
size_t count=0;
while (it != end())
{
count++;
it++;
}
return count;
}
// list element access
const T& front()const
{
assert(!empty());
return _head->_next->_data;
}
const T &back()const
{
assert(!empty());
return _head->_prev->_data;
}
T& front()
{
assert(!empty());
return _head->_next->_data;
}
T &back()
{
assert(!empty());
return _head->_prev->_data;
}
//list modifiers
void push_back(const T&x)
{
insert(end(), x);
//node *newnode = new node(x);//构造一个新节点
//node *tail = _head->_prev;
//tail->_next = newnode;
//newnode->_prev = tail;
//newnode->_next = _head;
//_head->_prev = newnode;
}
void push_front(const T&x)
{
insert(++begin(), x);
//node *newnode = new node(x);//构造一个新节点
//
//node *next = _head->_next;
//_head->_next = newnode;
//newnode->_prev=_head;
//newnode->_next = next;
//next->_prev = newnode;
}
void pop_front()
{
erase(++begin());
//assert(!empty());
//node *del = _head->_next;
重新连接头结点
//node *next = del->_next;
//_head->_next = next;
//next-> _prev = _head;
//delete del;
}
void pop_back()
{
erase(--end());
/*assert(!empty());
node *del = _head->_prev;
node *prev = del->_prev;
_head->_prev = prev;
prev->_next = _head;*/
}
iterator insert(iterator pos,const T &x)
{
//因为循环链表,迭代器位置不管怎么自增自减都在链表中
//不需要判断
node *newnode = new node(x);//构造一个新节点
node *cur = pos._node;
node *prev = cur->_prev;
newnode->_next = cur;
newnode->_prev = prev;
cur->_prev = newnode;
prev->_next = newnode;
return newnode;
}
iterator erase(iterator pos)
{
assert(pos!= end());//头不能删了
node *cur = pos._node;
node *prev = cur->_prev;
node *next = cur->_next;
prev->_next = next;
next->_prev = prev;
delete cur;
return next;
}
void clear()
{
iterator it = begin();
while (it != end())
{
erase(it++);
}
}
private:
node *_head;//双向带头循环链表
};
}