STL--List 常用接口模拟实现:
-
1、list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
-
2、list的底层是双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指
-
针指向其前一个元素和后一个元素。
1、常用接口介绍:
1>构造:
- list()------------------------------构造空的list
- list(size_type n, const value_type& val = value_type())------构造的list中包含n个值为val的元素
- list(const list& x)------------------拷贝构造函数
- list(InputIterator first,InputerIterator last)----------用[first,last)区间中的元素构造list
2、list iterator的使用:此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。
- begin() + end()----(正向迭代器)---返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器
- rbegin() + rend()----(反向迭代器)---返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置
3、list capacity
- empty()----------------检测list是否为空,是返回true,否返回false
- size()------------------返回list中有效节点的个数
4、list element access
- front()------------------返回list的第一个节点中值的引用
- back()------------------返回list的最后一个节点中值的引用
5、list modifiers
- push_front()------------------在list首元素前插入值为val的元素
- pop_front()-------------------删除list中第一个元素
- push_back()-------------------在list尾部插入值为val的元素
- pop_back()-------------------删除list中最后一个元素
- insert()-----------------------在list position 位置中插入值为val的元素
- erase()-----------------------删除list position位置的元素
- swap()----------------------交换两个list中的元素
- clear()-----------------------清空list中的有效元素
2、迭代器失效问题:
此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节 点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代 器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
3、总结:
1、实现List,首先要搞清楚List的底层结构:带头节点的双向循环链表。
2、整个List的实现过程,精华部分在于迭代器的重新封装,而迭代器又分为正向迭代器和反向迭代器,反向迭代器实际上是利用了正向迭代器进行封装,所以要模拟实现List,一定要先搞懂List中正向迭代器的封装。
3、正确使用模版,让你的代码更高效。
4、代码实现:
//STL-List 模拟实现
#include<iostream>
using namespace std;
namespace lxy
{
//list:带头节点的双向循环链表
template<class T>
struct ListNode //创建一个节点
{
ListNode(const T& data = T())
:_pNext(nullptr)
, _pPre(nullptr)
, _data(data)
{}
ListNode<T>* _pNext;
ListNode<T>* _pPre;
T _data;
};
//list迭代器:将节点类型的指针重新封装
template<class T>
struct List_iterator
{
typedef ListNode<T> Node; //给ListNode<T> 取别名为 Node,方便使用
typedef List_iterator<T> Self; //作用同上
public:
List_iterator(Node* pCur)
:_pCur(pCur)
{}
//按照指针方式进行应用
T& operator*()
{
return _pCur->_data;
}
T* operator->()
{
return &(_pCur->_data);
}
//移动
Self& operator++() //前置++
{
_pCur = _pCur->_pNext;
return *this;
}
Self operator++(int) //有参数的为后置++
{
Self temp(*this);
_pCur = _pCur->_pNext;
return temp;
}
Self& operator--() //前置--
{
_pCur = _pCur->_pPre;
return *this;
}
Self operator--(int) //有参数的为后置--
{
Self temp(*this);
_pCur = _pCur->_pPre;
return temp;
}
//比较
bool operator!=(const Self& s)
{
return _pCur != s._pCur;
}
bool operator==(const Self& s)
{
return _pCur == s._pCur;
}
Node* _pCur;
};
//反向迭代器封装
template<class Iterator,class T>
struct list_reverse_iterator
{
typedef list_reverse_iterator<Iterator, T> Self;
public:
list_reverse_iterator(Iterator it)
:_it(it)
{}
//按照指针方式进行应用
T& operator*()
{
Iterator temp = _it;
--temp;
return *temp;
}
T* operator->()
{
return &(Operator*());
}
//移动
Self& operator++()
{
--_it;
return *this;
}
Self& operator++(int)
{
Self temp (*this);
_it--;
return temp;
}
Self& operator--()
{
++_it;
return *this;
}
Self& operator--(int)
{
Self temp(*this);
_it++;
return temp;
}
//比较
bool operator!=(const Self& s)
{
return _it != s._it;
}
bool operator==(const Self& s)
{
return _it != s._it;
}
Iterator _it;
};
template<class T>
class list
{
typedef ListNode<T> Node;
public:
typedef List_iterator<T> iterator;
typedef list_reverse_iterator<iterator, T> reverse_iterator;
public:
//四种构造方法,赋值运算符重载,析构
//1、
list() //构造一个只含头节点的list
{
CreatHead();
}
//2、n个data
list(int n, const T& data) //这里int原本应该是size_t,但是使用区间构造时,会发生歧义,故改成int
{
CreatHead();
for (size_t i = 0; i < n; ++i)
{
push_back(data);
}
}
//3、区间构造
template<class Iterator>
list(Iterator first, Iterator last)
{
CreatHead();
while (first != last)
{
push_back(*first);
++first;
}
}
//4、拷贝构造
list(const list<T>& L)
{
CreatHead();
Node* pCur = L._pHead->_pNext;
while (pCur != L._pHead) //循环遍历完一圈
{
push_back(pCur->_data);
pCur = pCur->_pNext;
}
}
//赋值运算符重载 ’=‘
list<T>& operator=(const list<T>& L)
{
if (this != &L) //确保不是自己给自己赋值
{
clear(); //把自己的元素先清空
Node* pCur = L._pHead->_pNext;
while (pCur != _pHead)
{
push_back(pCur->_data);
pCur = pCur->_pNext;
}
}
return *this;
}
//析构
~list()
{
clear(); //清除所有元素
delete _pHead; //释放指针
}
public:
//迭代器相关操作
iterator begin()
{
return iterator(_pHead->_pNext);
}
iterator end()
{
return iterator(_pHead);
}
reverse_iterator rbegin()
{
return end();
}
reverse_iterator rend()
{
return begin();
}
public:
//容量相关操作
size_t size()const
{
size_t count = 0;
Node* pCur = _pHead->_pNext;
while (pCur != _pHead)
{
++count;
pCur = pCur->_pNext;
}
return count;
}
size_t empty()const
{
return _pHead->_pNext == _pHead; //让头节点指向自己,则为空链表
}
void resize(size_t newsize, const T& data = T())
{
size_t oldsize = size();
if (newsize > oldsize) //判断节点是否需要增多
{
//节点增多
for (size_t i=oldsize; i < newsize; ++i)
{
push_back(data);
}
}
else
{
//节点减少
for (size_t i = newsize; i < oldsize; ++i)
{
pop_back();
}
}
}
public:
//元素访问
T& front()
{
return _pHead->_pNext->_data;
}
const T&front()const
{
return _pHead->_pNext->_data;
}
T& back()
{
return _pHead->_pPre->_data;
}
const T& back()const
{
return _pHead->_pPre->_data;
}
public:
//Modify 修改
void push_back(const T& data)
{
insert(end(), data);
}
void pop_back()
{
erase(--end()); //顺时针转
}
void push_front(const T& data)
{
insert(begin(), data);
}
void pop_front()
{
erase(begin());
}
iterator insert(iterator pos, const T& data)
{
Node* pNewNode = new Node(data);//创建新节点
Node* pCur = pos._pCur;
pNewNode->_pPre = pCur->_pPre;
pNewNode->_pNext = pCur;
pNewNode->_pPre->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
return iterator(pNewNode);
}
iterator erase(iterator pos)
{
Node* pDelNode = pos._pCur;
if (pDelNode == _pHead) //不能删头节点,所以需要判空
{
return end();
}
Node* pRet = pDelNode->_pNext;
pDelNode->_pPre->_pNext = pDelNode->_pNext;
pDelNode->_pNext->_pPre = pDelNode->_pPre;
delete pDelNode; //销毁删除节点,防止内存泄露
return iterator(pRet);
}
void clear()
{
Node*pCur = _pHead->_pNext;
//头删法
//[]-->1-->2-->3...
while (pCur != _pHead) //判空
{
_pHead->_pNext = pCur->_pNext;
delete pCur;
pCur = _pHead->_pNext;
}
_pHead = _pHead->_pNext ; //形成只有头节点的空链表
_pHead = _pHead->_pPre ;
}
void swap(list<T>& L)
{
swap(_pHead,L._pHead)
}
private:
//创建一个头节点
void CreatHead()
{
_pHead = new Node;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
protected:
Node* _pHead;
};
}
//测试
#include<vector>
void TestList1()
{
lxy::list<int> L1;
lxy::list<int> L2(10, 5);
vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
lxy::list<int> L3(v.begin(), v.end());
lxy::list<int> L4(L3);
auto it = L2.begin();
while (it != L2.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : L3)
cout << e << " ";
cout << endl;
auto rit = L4.rbegin();
while (rit != L4.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
void TestList2()
{
lxy::list<int> L;
L.push_back(1);
L.push_back(2);
L.push_back(3);
L.push_back(4);
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.push_front(0);
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.pop_front();
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.pop_back();
cout << L.size() << endl;
cout << L.front() << endl;
cout << L.back() << endl;
L.clear();
if (L.empty())
cout << "clear is OK" << endl;
}
void TestList3()
{
lxy::list<int> L;
L.push_back(1);
L.push_back(2);
L.push_back(3);
L.resize(10, 5);
for (auto e : L)
cout << e << " ";
cout << endl;
L.resize(2);
for (auto e : L)
cout << e << " ";
cout << endl;
}
int main()
{
//TestList1();
//TestList2();
TestList3();
return 0;
}