list是带头双向循环链表,与vector的底层结构不一样,vector是连续的空间,list的每个节点是独立的空间。
模拟实现list主要有以下类:
struct ListNode//节点类
struct ListIterator//正向迭代器类
struct ReverseIterator//反向迭代器类
class list//模拟实现list类
每个节点都有它的指针域和数据域,因为是双向的,所以指针域有两个分别为前指针和后指针。同时写个构造函数,用来创建新节点。
template<class T>
struct ListNode//节点类
{
ListNode<T>* _prev;
ListNode<T>* _next;
T _val;
ListNode(const T& x = T())
:_prev(nullptr)
,_next(nullptr)
,_val(x)
{}
};
使用类模板可以传任意类型。
私有成员变量是链表的头,即哨兵位节点,类型是节点类指针类型,方便连接其他节点。
节点类的名字有点长,可以重命名简化:
typedef ListNode<T> Node;
成员变量:
private:
Node* _head;
初始化是对哨兵位的初始化,即让哨兵位成为一个节点,这个节点不放数据,只是用来连接。它的前指针和后指针都是指向自己。
void Init()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
1️⃣无参构造
复用初始化即可。
list()
{
Init();
}
2️⃣有参构造1
先对哨兵位节点初始化,然后n为多少尾插多少元素
//有参构造1
list(int n, const T& x = T())
{
Init();
while (n--)
{
push_back(x);
}
}
3️⃣有参构造2
该函数的参数只要是迭代器就行,先初始化哨兵位,然后逐个尾插迭代器指向的内容。
template <class Iterator>
list(Iterator first, Iterator last)
{
Init();
while (first != last)
{
push_back(*first);
++first;
}
}
先初始化哨兵位,然后从被拷贝的链表里逐个节点尾插到新链表里。
//拷贝构造
list(const list<T>& lt)
{
Init();
for (const auto& e : lt)
{
push_back(e);
}
}
1️⃣写法1
判断被赋值的对象与要赋值的对象是否地址相同,相同直接返回当前对象,不相同先清理链表的元素,然后用范围for逐个尾插。
//写法1
list<T>& operator=(const list<T>& lt)
{
if (this != <)
{
clear();
for (const auto& e : lt)
{
push_back(e);
}
}
return *this;
}
1️⃣写法2
这个不多说了,还是复用交换函数,然后返回this指针。
//写法2
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
先清理链表里的所有元素,除了哨兵位节点,然后释放哨兵位节点,置空。
//析构
~list()
{
clear();
delete _head;
_head = nullptr;
}
//交换
void swap(const list<T>& lt)
{
std::swap(_head, lt._head);
}
//清理
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
}
//获取元素个数
size_t size() const
{
Node* cur = _head->_next;
size_t count = 0;
while (cur != _head)
{
count++;
cur = cur->_next;
}
return count;
}
//判空
bool empty() const
{
return _head->_next == _head;
}
//获取第一个节点数据
T& front()
{
return _head->_next->_val;
}
const T& front()const
{
return _head->_next->_val;
}
//获取最后一个节点数据
T& back()
{
return _head->_prev->_val;
}
const T& back()const
{
return _head->_prev->_val;
}
//pos位置插入
iterator insert(iterator pos, const T& x)
{
Node* newnode = new Node(x);//创建新节点
Node* cur = pos._node;//得到pos位置的节点
Node* Prev = cur->_prev;//pos位置前一个节点
newnode->_prev = Prev;//Prev<=>newnode
Prev->_next = newnode;
newnode->_next = cur;//newnode<=>cur
cur->_prev = newnode;
return newnode;//返回
}
//pos位置删除
iterator erase(iterator pos)
{
assert(pos != _head);//pos不能是哨兵位节点
Node* cur = pos._node; // 得到pos位置的节点
Node* Prev = cur->_prev;//pos位置前一个节点
Node* Next = cur->_next;//pos位置后一个节点
Prev->_next = Next;//Prev<=>Next
Next->_prev = Prev;
delete cur;//清理cur
return Next;//返回
}
复用begin 和 end
//尾插
void push_back(const T& x)
{
insert(end(), x);
}
//头插
void push_front(const T& x)
{
insert(begin(), x);
}
//尾删
void pop_back()
{
erase(--end());
}
//头删
void pop_front()
{
erase(begin());
}
分为两种:
begin返回第一个节点的位置,end返回最后一个节点的下一个位置
//正向迭代器遍历
iterator begin()
{
return _head->_next;
}
iterator end()
{
return _head;
}
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;
}
rbegin返回最后一个节点的下一个位置,rend返回第一个节点的位置
//反向迭代器遍历
reverse_iterator rbegin()
{
return end();
}
reverse_iterator rend()
{
return begin();
}
const_reverse_iterator rbegin() const
{
return end();
}
const_reverse_iterator rend() const
{
return begin();
}
迭代器类是对迭代器的行为另作处理。在vector里,iterator++就是正常的++,因为空间是连续的。但是list不是,如果还是像前面的++一样就不会指向下一个节点,因为list的每个节点是独立的空间,不连续,所以要对迭代器的++、–等操作符作封装,重新定义它们的行为。
template<class T, class Ref, class Ptr>
struct ListIterator//正向迭代器类
{
typedef ListNode<T> Node;
typedef ListIterator<T, Ref, Ptr> self;
Node* _node;
//构造
ListIterator(Node* x)
:_node(x)
{}
//前置++
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;//返回临时对象,不能引用
}
// *
Ref operator*()
{
return _node->_val;//返回该节点的数据
}
// ->
Ptr operator->()
{
return &_node->_val;//返回该节点的数据的成员(数据是自定义类型)
}
//判断不相等
bool operator!=(const self& lt)
{
return _node != lt._node;
}
//判断相等
bool operator==(const self& lt)
{
return _node == lt._node;
}
};
这里的Ref、Ptr是模板参数,这样写更方便,不管传过来的是const类型还是非const类型,都可以在一段代码里处理好,减少了代码冗余。
在list类里重命名:
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
反向迭代器类其实是对正向迭代器作了一层封装,它的第一个模板参数是iterator,后面两个与正向迭代器相同,作用在rbegin和rend函数上。
下面的图可以知道正、反向迭代器在链表里的位置:
可以看出,它们是对称的。但由于是这样的结构,所以反向迭代器的++、- - 以及解引用操作就会有些不一样。
template<class Iterator, class Ref, class Ptr>
struct ReverseIterator//反向迭代器类
{
typedef ReverseIterator<Iterator, Ref, Ptr> self;
Iterator cur;
ReverseIterator(Iterator x)
:cur(x)
{}
//前置++
self& operator++()
{
--cur;//++就是--
return *this;
}
//后置++
self operator++(int)
{
Iterator tmp = cur;
--cur;
return tmp;
}
//前置--
self& operator--()
{
++cur;//--就是++
return *this;
}
//后置--
self operator--(int)
{
Iterator tmp = cur;
++cur;
return tmp;
}
// * 解引用前一个位置的元素
Ref operator*()
{
Iterator tmp = cur;
--tmp;
return *tmp;
}
// ->
Ptr operator->()
{
return &(operator*());//复用
}
//判断不相等
bool operator!=(const self& it)
{
return cur != it.cur;
}
//判断相等
bool operator==(const self& it)
{
return cur == it.cur;
}
};
在list类里重命名:
typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;
#include
#include
using namespace std;
namespace yss
{
template<class T>
struct ListNode//节点类
{
ListNode<T>* _prev;
ListNode<T>* _next;
T _val;
ListNode(const T& x = T())
:_prev(nullptr)
,_next(nullptr)
,_val(x)
{}
};
template<class T, class Ref, class Ptr>
struct ListIterator//正向迭代器类
{
typedef ListNode<T> Node;
typedef ListIterator<T, Ref, Ptr> self;
Node* _node;
//构造
ListIterator(Node* x)
:_node(x)
{}
//前置++
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;
}
// *
Ref operator*()
{
return _node->_val;
}
// ->
Ptr operator->()
{
return &_node->_val;
}
//判断不相等
bool operator!=(const self& lt)
{
return _node != lt._node;
}
//判断相等
bool operator==(const self& lt)
{
return _node == lt._node;
}
};
template<class Iterator, class Ref, class Ptr>
struct ReverseIterator//反向迭代器类
{
typedef ReverseIterator<Iterator, Ref, Ptr> self;
Iterator cur;
ReverseIterator(Iterator x)
:cur(x)
{}
//前置++
self& operator++()
{
--cur;
return *this;
}
//后置++
self operator++(int)
{
Iterator tmp = cur;
--cur;
return tmp;
}
//前置--
self& operator--()
{
++cur;
return *this;
}
//后置--
self operator--(int)
{
Iterator tmp = cur;
++cur;
return tmp;
}
// * 解引用前一个位置的元素
Ref operator*()
{
Iterator tmp = cur;
--tmp;
return *tmp;
}
// ->
Ptr operator->()
{
return &(operator*());
}
//判断不相等
bool operator!=(const self& it)
{
return cur != it.cur;
}
//判断相等
bool operator==(const self& it)
{
return cur == it.cur;
}
};
template<class T>
class list//模拟实现list
{
public:
typedef ListNode<T> Node;
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
typedef ReverseIterator<iterator, T&, T*> reverse_iterator;
typedef ReverseIterator<iterator, const T&, const T*> const_reverse_iterator;
//正向迭代器遍历
iterator begin()
{
return _head->_next;
}
iterator end()
{
return _head;
}
const_iterator begin() const
{
return _head->_next;
}
const_iterator end() const
{
return _head;
}
//反向迭代器遍历
reverse_iterator rbegin()
{
return end();
}
reverse_iterator rend()
{
return begin();
}
const_reverse_iterator rbegin() const
{
return end();
}
const_reverse_iterator rend() const
{
return begin();
}
// 初始化
void Init()
{
_head = new Node;
_head->_next = _head;
_head->_prev = _head;
}
//无参构造
list()
{
Init();
}
//有参构造1
list(int n, const T& x = T())
{
Init();
while (n--)
{
push_back(x);
}
}
//有参构造2
template <class Iterator>
list(Iterator first, Iterator last)
{
Init();
while (first != last)
{
push_back(*first);
++first;
}
}
//交换
void swap(const list<T>& lt)
{
std::swap(_head, lt._head);
}
//拷贝构造
list(const list<T>& lt)
{
Init();
for (const auto& e : lt)
{
push_back(e);
}
}
//赋值重载
//写法1
/*list& operator=(const list& lt)
{
if (this != <)
{
clear();
for (const auto& e : lt)
{
push_back(e);
}
}
return *this;
}*/
//写法2
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
//清理
void clear()
{
iterator it = begin();
while (it != end())
{
it = erase(it);
}
}
//析构
~list()
{
clear();
delete _head;
_head = nullptr;
}
//获取元素个数
size_t size() const
{
Node* cur = _head->_next;
size_t count = 0;
while (cur != _head)
{
count++;
cur = cur->_next;
}
return count;
}
//判空
bool empty() const
{
return _head->_next == _head;
}
//获取第一个节点数据
T& front()
{
return _head->_next->_val;
}
const T& front()const
{
return _head->_next->_val;
}
//获取最后一个节点数据
T& back()
{
return _head->_prev->_val;
}
const T& back()const
{
return _head->_prev->_val;
}
//尾插
void push_back(const T& x)
{
insert(end(), x);
}
//头插
void push_front(const T& x)
{
insert(begin(), x);
}
//尾删
void pop_back()
{
erase(--end());
}
//头删
void pop_front()
{
erase(begin());
}
//pos位置插入
iterator insert(iterator pos, const T& x)
{
Node* newnode = new Node(x);//创建新节点
Node* cur = pos._node;//得到pos位置的节点
Node* Prev = cur->_prev;//pos位置前一个节点
newnode->_prev = Prev;//Prev<=>newnode
Prev->_next = newnode;
newnode->_next = cur;//newnode<=>cur
cur->_prev = newnode;
return newnode;//返回
}
//pos位置删除
iterator erase(iterator pos)
{
assert(pos != _head);//pos不能是哨兵位节点
Node* cur = pos._node; // 得到pos位置的节点
Node* Prev = cur->_prev;//pos位置前一个节点
Node* Next = cur->_next;//pos位置后一个节点
Prev->_next = Next;//Prev<=>Next
Next->_prev = Prev;
delete cur;//清理cur
return Next;//返回
}
private:
Node* _head;
};
}
#include "list.h"
int main()
{
/*yss::list lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_front(100);
lt.push_front(200);
lt.push_front(300);
lt.pop_back();
lt.pop_front();
lt.pop_front();
auto it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;*/
yss::list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
yss::list<int>::reverse_iterator it = lt.rbegin();
while (it != lt.rend())
{
cout << *it << " ";
++it;
}
cout << endl;
return 0;
}