文章目录
- list类的介绍
- list类的常用接口介绍
- 构造相关
- 带参构造
- 迭代器区间构造
- 拷贝构造
- 容量相关的接口
- size
- empty
- 数据访问及遍历相关的接口
- front
- back
- begin + end
- 修改数据相关的接口
- push_front
- pop_front
- push_back
- pop_back
- insert
- erase
- clear
- 构造相关
- list类的模拟实现(含各类接口)
list类的介绍
list是STL标准库提供的一个非常好用的存储容器,list的底层是一个带头双向循环链表,使我们学习STL的重点。
list类的常用接口介绍
构造相关
带参构造:
作用:构造的链表中包含n个val值的元素。
迭代器区间构造:
作用:使用迭代器区间中的元素来生成一个list对象,内容和传参的迭代器内容一样,注意传参时迭代器内的数据类型要相同。
拷贝构造:
作用:用一个已经存在的list对象来创建一个新的list对象,内容是相同的。
容量相关的接口
size:
作用:返回list对象中有效节点的个数。
empty:
作用:判断list对象是否为空,如果是返回true,不为空返回false。
数据访问及遍历相关的接口
front:
作用:返回list对象头部节点中值的引用。
back:
作用:返回list对象尾部节点中值的引用。
begin + end:
begin作用:获取list对象中第一个元素
的地址
end作用:获取list对象中最后一个元素的下一个位置
的地址
注意:
1、迭代器是STL中通用的遍历容器方式,迭代器是一种行为像指针一样的类型
,但是迭代器的底层实现是不是指针不确定,具体看容器的底层实现方式,迭代器的使用方式也很像指针,迭代器++
就是访问当前位置的下一个数据,- -(自减)
就是前一个。
2、第二个const接口是提供给const对象调用的,普通的对象和const对象的迭代器是不一样的,不能混淆,因为const迭代器是不允许通过迭代器来修改数据的。
修改数据相关的接口
push_front:
作用:在list中第一个元素之前插入一个值为val的元素。
pop_front:
作用:删除list中第一个元素。
push_bcak:
作用:在list中尾部插入一个值为val的元素。
pop_back:
作用:删除list中最后一个元素。
insert:
作用:接口1是在迭代器对应位置之前插入一个值为val的元素,接口2是在迭代器对应位置插入n个值为val的元素,接口3是在迭代器对应位置插入某段迭代器区间内的数据。
erase:
作用:删除迭代器对应位置的元素,接口2是删除对应的迭代器区间内的所有元素。
claer:
作用:清空list中的所有有效元素。
list类的模拟实现(含各类接口)
#include<iostream>
#include<assert.h>
using namespace std;
namespace Lh
{
template<class T>
struct list_node //节点
{
list_node(const T& x = T())//构造函数
:_date(x)
, _next(nullptr)
, _prev(nullptr)
{}
T _date;
list_node<T>* _next;
list_node<T>* _prev;
};
template<class T, class Ref, class Ptr> //实例化是普通对象就是普通迭代器,const对象就是const迭代器
struct __list_iterator //迭代器
{
typedef list_node<T> Node;
typedef __list_iterator<T, Ref, Ptr> iterator;
Node* _node;
__list_iterator(Node* node)
:_node(node)
{}
bool operator!=(const iterator& it) const
{
return _node != it._node;
}
bool operator==(const iterator& it) const
{
return _node == it._node;
}
// T& operator*()
Ref operator*()
{
return _node->_date;
}
// T* operator->()
Ptr operator->() //返回T*的指针 让结构体也能像指针一样去访问数据
{
return &(operator*());
}
// ++it
iterator& operator++()
{
_node = _node->_next;
return *this;
}
// it++
iterator& operator++(int)
{
iterator tmp(*this);
_node = _node->_next;
return tmp;
}
// --it
iterator& operator--()
{
_node = _node->_prev;
return *this;
}
// it--
iterator& operator--(int)
{
iterator tmp(*this);
_node = _node->_prev;
return tmp;
}
};
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; //const迭代器
list() //构造函数
{
empty_init();
}
void empty_init() //创建哨兵位头结点 并初始化
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
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);
}
template <class InputIterator>
list(InputIterator first, InputIterator last) //迭代器区间构造
{
empty_init();
while (first != last)
{
push_back(*first);
++first;
}
}
void swap(list<T>& x) //交换链表结点
{
std::swap(_head, x._head);
}
//lt2(lt1)
list(const list<T>& lt) //拷贝构造
{
empty_init();
list<T> tmp(lt.begin(), lt.end());
swap(tmp);
}
list<T>& operator=(list<int> lt) //赋值重载
{
swap(lt);
return *this;
}
~list() //析构函数
{
clear();
delete _head;
_head = nullptr;
}
void clear() //清理链表
{
iterator it = begin();
while (it != end())
{
it = erase(it); //不用++ erase返回的是下一个结点
}
}
void push_back(const T& x)
{
//Node* tail = _head->_prev;
//Node* newnode = new Node(x);
//tail->_next = newnode;
//newnode->_prev = tail;
//newnode->_next = _head;
//_head->_prev = newnode;
insert(end(), x);
}
void push_front(const T& x)
{
insert(begin(), x);
}
iterator insert(iterator pos, const T& x)
{
Node* cur = pos._node;
Node* prev = pos._node->_prev;
Node* newnode = new Node(x);
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = cur;
cur->_prev = newnode;
return iterator(newnode);
}
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 = next;
next->_prev = prev;
delete cur;
return iterator(next);
}
private:
Node* _head;
};
}