list.h
#pragma once
#include <iostream>
namespace TCH
{
template<class T>
struct list_node
{
list_node(const T& data)
:_next(nullptr)
,_prev(nullptr)
,_data(data)
{}
list_node<T>* _next;
list_node<T>* _prev;
T _data;
};
template<class T, class Ref, class Ptr>
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;
}
self& operator++ ()
{
_node = _node->_next;
return *this;
}
self operator++ (int)
{
list_iterator tmp = *this;
//++(*this);
_node =_node->_nextl
return tmp;
}
Ptr operator-> ()const
{
//return &(operator*());
return &_node->_data;
}
self& operator-- ()
{
_node = _node->_prev;
return *this;
}
self operator-- (int)
{
list_iterator tmp = *this;
//++(*this);
_node = _node->_prev;
return tmp;
}
bool operator!= (const self it)
{
return _node != it;
}
};
template<class T>
class List
{
typedef list_node<T> Node;
typedef list_iterator<T, T&, T*> iterator;
typedef list_iterator</*const*/T, const T&, const T*> const_iterator;
public: //这里加const是错的,会发生类型不匹配,一定要弄清楚模板是给谁用的!
const_iterator begin()const
{
return iterator(_head->_next);
}
const_iterator end()const
{
return iterator(_head);
}
//iterator begin()const//-----→会出问题,因为我是const对象,你却返回普通迭代器,则可以被修改
//{
// //return _head->_next------→也可以,因为单参数类型支持隐式类型转换
// return iterator(_head->_next);
//}
//iterator end()const
//{
// return iterator(_head);
//}
iterator begin()
{
//return _head->_next------→也可以,因为单参数类型支持隐式类型转换
return iterator(_head->_next);
}
iterator end()
{
return iterator(_head);
}
List()
{
_head = new Node();//---→相当于缺省值
_head->_next = _head;
_head->_prev = _head;
}
List(iterator begin, iterator end)//----->为现代写法做铺垫
:_head = new Node()
,_head->_next = _head
,_head->_prev = _head
{
while (first != end)
{
push_back(*first);
++first;
}
}
void swap(List<T>& lt)
{
std::swap(_head, lt._head);
}
List(const List<T>& lt)//-------→现代写法
:_head = new Node()
, _head->_next = _head
, _head->_prev = _head
{
List<T> tmp(lt.begin(), lt.end());
swap(tmp);
}
List<T>& operator= (const List<T> tmp)//----->现代写法
{
//clear();----->根本不需要,因为tmp会给你搽屁股的!
swap(tmp);
return *this;
}
/*List(const List<T>& lt)//----传统写法!
:_head = new Node()
,_head->_next = _head
,_head->_prev = _head
{
for (auto e : lt)
{
push_back(e);//------复用的妙呀!
}
}*/
~List()
{
clear();
delete _head;
_head = nullptr;
}
void clear()
{
iterator it = begin();//------复用的很巧妙
while (it != end())
{
erase(it);
it++;
}
}
iterator erase(iterator pos)
{
assert(end() != pos);
Node* cur = pos._node;
Node* prev = cur->_prev;
Node* next = cur->_next;
prev->_next = next;
next->_prev = prev;
delete cur;
return iterator(next);//返回被删除节点的后面一个(匿名对象构造)
}
void pop_back()
{
erase(--end());
}
void pop_front()
{
erase(begin());
}
void insert(iterator pos, const T& val)
{
Node* new_node = new Node(val);
Node* cur = pos._node;
Node* prev = cur->_prev;
new_node->_next = cur;
new_node->_prev = prev;
cur->_prev = new_node;
prev->_next = new_node;
}
void push_back(const T& data)
{
insert(end(), data);
/*Node* tail = _head->_prev;
Node* new_node = new Node(data);
tail->_next = new_node;
new_node->_prev = tail ;
new_node->_next = _head;
_head->_prev = new_node; */
}
void push_front(const T& data)
{
insert(begin(), data);
}
private:
Node* _head;
};
}
实现重载->的原因
struct AA
{
AA(int a1 = 0, int a2 = 0)
:_a1(a1)
, _a2(a2)
{}
int _a1;
int _a2;
};
list<AA> lt;
lt.push_back(AA(1, 1));
lt.push_back(AA(2, 2));
lt.push_back(AA(3, 3));
lt.push_back(AA(4, 4));
迭代器模拟的是指针行为
// int* it *it
// AA* it *it it->
list<AA>::iterator it = lt.begin();
while (it != lt.end())
{
//cout << (*it)._a1 << "-"<< (*it)._a2 <<" ";
cout << it->_a1 << "-" << it->_a2 << " ";
++it;
}
关于typedef list_iterator</const/T, const T&, const T*> const_iterator;
若
const_iterator begin()const
{
return iterator(_head->_next);
}
因为你这里的_head->_next是Node* <T>类型,经过你iterator(_head->_next)进行调iterator类里的构造函数
list_iterator(Node* node)
:_node(node);
{}
而你的_node是Node*<const T>类型,所以类型不匹配!
反向迭代器的实现
✳️与正向迭代器相比,除了++/–时的方向相反,其他操作基本一致;
我们有 string::iterator
vector::iterator
list:iterator
duque::iterator
map/set::iterator
❓能不能封装适配一下,生成对应的反向迭代器呢?
那怎么适配呢?STL就搞出了这么一个类:reverse_iterator,是由封装适配实现的,这样你传list的正向迭代器给我,我就是list的反向迭代器;你传vector的正向迭代器给我,我就是vector的反向迭代器…我的反向迭代器只需要一份,你传给我什么,我就是什么。
我用正向迭代器在我类里面定义个成员变量,正向迭代器是一个类型,它里面是包含了指针的,那么我对正向迭代器封装一下就可以变成反向迭代器了。(🌟然后operator*会有点不一样,反向迭代器取得不是当前位置的,而是当前位置的前面一个)反向迭代器的++就是正向迭代器的–,差不多其他操作都一样。
rebegin()使用end()来构造的;它这里rebegin()和reend()达到了对称设计
代码实现
template<class Iterator, class Ref, class Ptr>
class Reverse_iterator
{
public:
typedef Reverse_iterator<Iterator, Ref, Ptr> self;
Iterator _it;
reverse_iterator(Iterator it)
:_it(it)
{}
Ref operator* ()
{
Iterator tmp = _it;
return *(--tmp);
}
Ptr operator-> ()
{
return &(operator* ());
}
self& operator++ ()const
{
--_it;
return *this;
}
self& operator-- ()const
{
++_it;
return *this;
}
bool operator!= (const self& it)
{
rerurn _it != it._it;
}
};
insert迭代器不失效
list的insert不存在野指针,也不存在意义失效的问题
要求在偶数前面插入这个数的10倍
auto it1 = it.begin();
while(it1 != it.end())
{
if(*it1 % 2 == 0)
{
it.insert(it1, *it1 * 10);
}
++it;
}
erase迭代器失效问题
存在野指针的问题
auto it1 = it.begin();
while(it1 != it.end())
{
if(*it1 % 2 == 0)
{
it.erase(it1);
}
else
{
++it1;
}
}
解决办法:返回被删除的节点的后面一个
不得不提的clear复用
void clear()
{
iterator it = begin();//------复用的很巧妙
while (it != end())
{
erase(it);
it++;
}
}