一、模拟实现list
要模拟实现list,必须要熟悉list的底层结构以及其接口的含义,大家可以看我关于list接口的博客c++:list-CSDN博客
1.1 list成员变量
list是一个双向带头链表,我们在定义成员变量时应该先定义出list单个的节点的类型。
1.1.1 list节点
cpp
// List的节点类
template<class T>
struct ListNode
{
//默认构造 T()是一个匿名对象
ListNode(const T& val = T())
:_pPre(nullptr)
,_pNext(nullptr)
,_val(val)
{}
ListNode<T>* _pPre;//指向上一个节点
ListNode<T>* _pNext;//指向下一个节点
T _val; //节点的数据
};
在c++中class 和struct 的主要区别就是struct 中的成员变量和成员函数的默认访问权限是public,而class中的成员变量和成员函数的默认访问权限是private,这里直接用struct更方便。
1.1.2 list的成员变量
cpp
class List{
typedef ListNode<T> Node;
typedef Node* PNode;
private:
PNode _pHead;
size_t _size = 0;
}
这里我们把节点类型重命名为Node,又把节点的指针重命名为PNode。List的成员变量只有一个头节点的指针和节点的数量。(List底层是一个带头双向链表)
1.2 list的默认成员函数
1.2.1 默认构造
cpp
public:
///
// List的构造
//void CreateHead();
//PNode _pHead;
void CreateHead()
{
_pHead = new Node;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
_size = 0;
}
list()
{
CreateHead();
}
1.2.2 构造函数
1.2.2.1 list中包含n个值为val的元素
cpp
list(int n, const T& value = T())
{
CreateHead();
int i = n;
while (i--)
{
push_back(value);
}
}
1.2.2.2 用迭代器区间初始化list
cpp
template <class Iterator>
list(Iterator first, Iterator last)
{
CreateHead();
while (first!=last)
{
push_back(*first);
++first;
}
}
1.2.3 拷贝构造
cpp
list(const list<T>& lt)
{
CreateHead();
// 用l中的元素构造临时的temp,然后与当前对象交换
list<T> temp(lt.begin(), lt.end());
this->swap(temp);
}
void swap(list<T>& l)
{
std::swap(l._pHead, _pHead);
std::swap(l._size, _size);
}
1.2.4 赋值运算符重载
cpp
list<T>& operator=(list<T> lt)
{
swap(lt);
return *this;
}
void swap(list<T>& l)
{
std::swap(l._pHead, _pHead);
std::swap(l._size, _size);
}
1.2.5 析构函数
cpp
~list()
{
clear();
delete _pHead;
_pHead = nullptr;
}
void clear()
{
iterator it = begin();
while (it != end())
{
//不用++防止迭代器失效
it=erase(it);
}
_size = 0;
_pHead = nullptr;
}
1.3 list capacity
cpp
size_t size()const
{
return _size;
}
bool empty()const
{
return _size == 0;
}
1.4 list 迭代器
正反向迭代器和const版本,反向迭代器是依靠正向迭代器实现,迭代器是通过对节点的指针进行封装,通过代码实现你想要的结果。
1.4.1 正向迭代器
cpp
template<class T, class Ref, class Ptr>
struct ListIterator
{
typedef ListNode<T>* PNode;
typedef ListIterator<T, Ref, Ptr> Self;
//typedef ListIterator<T, T&, T*> iterator;
//typedef ListIterator<T, const T&, const T&> const_iterator;
public:
ListIterator(PNode pNode = nullptr)
{
_pNode = pNode;
}
Ref operator*()
{
return _pNode->_val;
}
Ptr operator->()
{
return &(_pNode->_val);
}
Self& operator++()
{
_pNode = _pNode->_pNext;
return *this;
}
Self operator++(int)
{
Self tmp = *this;
_pNode = _pNode->_pNext;
return tmp;
}
Self& operator--()
{
_pNode = _pNode->_pPre;
return *this;
}
Self& operator--(int)
{
Self tmp = *this;
_pNode = _pNode->_pPre;
return tmp;
}
bool operator!=(const Self& l)
{
return l._pNode != _pNode;
}
bool operator==(const Self& l)
{
return l._pNode == _pNode;
}
PNode _pNode;
};
1.4.2 begin,cbegin,end,cend,rbegin,rend,crbegin,crend
cpp
// List Iterator
public:
typedef ListNode<T> Node;
typedef Node* PNode;
typedef ListIterator<T, T&, T*> iterator;
typedef ListIterator<T, const T&, const T*> const_iterator;
typedef ListReverseIterator<iterator,T, T&, T*> reverse_iterator;
typedef ListReverseIterator<iterator,T, const T&, const T*> const_reverse_iterator;
iterator begin()
{
return _pHead->_pNext;
}
iterator end()
{
return _pHead;
}
const_iterator begin()const
{
return _pHead->_pNext;
}
const_iterator end()const
{
return _pHead;
}
// ListreverseIterator
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
const_reverse_iterator rbegin()const
{
return reverse_iterator(end());
}
const_reverse_iterator rend()const
{
return reverse_iterator(begin());
}
1.4.3 反向迭代器
cpp
template<class iterator, class T, class Ref, class Ptr>
struct ListReverseIterator
{
public:
typedef ListReverseIterator<iterator,T, Ref, Ptr> Self;
ListReverseIterator(iterator it)
:_it(it)
{}
Ref operator*()
{
//解引用不影响迭代器
iterator tmp = _it;
return *--tmp;
}
Ptr operator->()
{
return &(operator*());
}
Self& operator++()
{
--_it;
return *this;
}
Self operator++(int)
{
Self tmp = _it--;
return tmp;
}
Self& operator--()
{
++_it;
return *this;
}
Self& operator--(int)
{
Self tmp = --_it;
return tmp;
}
bool operator!=(const Self& l)
{
return _it!= l._it;
}
bool operator==(const Self& l)
{
return _it == l._it;
}
private:
iterator _it;
};
1.5 list Modify
这里的erase和insert要返回一个迭代器来防止迭代器失效的问题。
cpp
void push_back(const T& val) { insert(end(), val); }
void pop_back() { erase(--end()); }
void push_front(const T& val) { insert(begin(), val); }
void pop_front() { erase(begin()); }
// 在pos位置前插入值为val的节点
iterator insert(iterator pos, const T& val)
{
Node* newNode = new Node(val);
Node* tmp = pos._pNode;
Node* prev = tmp->_pPre;
newNode->_pNext = tmp;
tmp->_pPre = newNode;
newNode->_pPre = prev;
prev->_pNext = newNode;
_size++;
return pos;
}
// 删除pos位置的节点,返回该节点的下一个位置
iterator erase(iterator pos)
{
Node* tmp = pos._pNode;
Node* tail = tmp->_pNext;
Node* prev = tmp->_pPre;
delete tmp;
tail->_pPre = prev;
prev->_pNext = tail;
_size--;
return iterator(tail);
}
1.6 list Access
cpp
T& front()
{
return _pHead->_pNext->_val;
}
const T& front()const
{
return _pHead->_pNext->_val;
}
T& back()
{
return _pHead->_pPre->_val;
}
const T& back()const
{
return _pHead->_pPre->_val;
}
总结
list的难点主要在迭代器的封装,反向迭代器的实现,和模板。
蟹蟹观看!点赞!关注!收藏!评论!一键三连!