构造函数 | 接口说明 |
list() | 构造空的list |
list(size_type n,const value_type* val = value_type()) | 构造的list中包含n个值为val的元素 |
list(const list&x) | 拷贝构造函数 |
list(Inputlterator firs,Inputlterator last) | 用[list,last)区间中的元素构造 |
void MakeListTest() {
list l1; //空
list l2(4,100); //l2中放置4个值为100的元素
list l3(l2.begin(),l2.end()); //用l2中的[begin,end)区间构造l3
list l4(l3); //用l3拷贝构l4
//以数组为迭代器区间构造l5
int array[] = {9, 5, 2, 7};
list l5(array,array+sizeof(array)/sizeof(int));
//使用迭代器的当时打印l5
for (list::iterator it = l5.begin(); it != l5.end();++it) {
cout << *it << " ";
}
cout << endl;
for (auto x : l5)
cout << x << " ";
cout << endl;
此处,可以暂时把迭代器理解为一个指针,该指针指向 list 中的某个节点;
函数声明 | 接口说明 |
begin() | 返回第一个元素的迭代器 |
end() | 返回最后一个元素下一个位置的迭代器 |
rbegin() | 返回第一个元素的reverse_iterator,及end位置 |
rend() | 返回最后一个元素下一个位置reverse_iterator,即begin位置 |
cbegin() |
返回第一个元素的const_iterator(C++11) |
cend() |
但回最后一个元素下一个位置的const_iterator(C++11) |
crbegin() | 即credn()的位置(C++11) |
crend() | 即crbegin()的位置(C++11) |
void IteratorListTest() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
list ll(array, array + sizeof(array) / sizeof(int));
//正向迭代器
for (list::iterator it = ll.begin(); it != ll.end();++it) {
cout << *it << " ";
}
cout << endl;
//反向迭代器
for (list::reverse_iterator it = ll.rbegin(); it != ll.rend();++it) {
cout << *it << " ";
}
cout << endl;
//const 正向迭代器(C++11)
auto cit = ll.cbegin();
cout << typeid(cit).name() << endl;
//const 反向迭代器(C++11)
auto crit = ll.crbegin();
cout << typeid(crit).name() << endl;
}
总结:
函数声明 | 接口说明 |
bool empty() const | 检测list是否为空,是返回true,否则返回false |
size_t size() const | 返回list中有效节点的个数 |
void ListCapacityTest() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list ll(array, array + sizeof(array) / sizeof(int));
//打印list 中有效节点的个数
cout << ll.size() << endl;
//检测list 是否为空
if (ll.empty())
cout << "empty()" << endl;
else
for (auto a : ll)
cout << a << " ";
cout << endl;
}
函数声明 | 接口说明 |
reference front() | 返回list的第一个节点中值的引用 |
const_reference front() const | 返回list的第一个节点中值的const引用 |
reference back() |
返回list的最后一个节点中值的引用 |
const_reference back() const | 返回list的最后一个节点中值的const引用 |
void ListElementAccessTest() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list ll(array, array + sizeof(array) / sizeof(int));
for (auto a : ll)
cout << a << " ";
cout << endl;
//将list 中的第一个节点的值 和 最后一个节点的值 改为 20;
ll.front() = 20;
ll.back() = 20;
for (auto a : ll)
cout << a << " ";
cout << endl;
const list ll2(array,array+sizeof(array)/sizeof(int));
const int& ca = ll2.front();
}
函数声明 | 接口说明 |
void push_front(const value_type& val) | 头插 |
void pop_front() | 头删 |
void push_back(const value_type& val) | 尾插 |
void pop_back() | 尾删 |
template void empalce_front(Args&&.. args)(C++11) |
在list的第一个元素前根据参数直接构造元素 |
tmplate void emplace_back(Args&&.. args) (C++11) |
在list的最后一元素后位置根据参数直接构造元素 |
iterator insert(iterator pos,const value_type& val) | 在pos位置插入值为 val 的元素 |
void insert(iterator pos,size_type n,const value_type& val) | 在pos为插入 n 个值为val 的元素 |
void insert(iterator pos,Inputlterator firsr,inputlterator last) | 在pos为插入[first,last)区间中的元素 |
iterator erase(iterator pos) | 删除pos位置的元素 |
iterator erase(iterator first,iterator last) | 删除[first,list)中的元素 |
void swap(list& x) | 交换两个list中的元素 |
void resize(size_type n,value_type val = value_type()) | 将list 中有效元素个数改变为n,多出的元素用val 填充 |
void clear() | 清空list 所有元素 |
测试==》》
1、push_front / pop_front / push_back / pop_back
void ListModifiersTest() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list L(array, array + sizeof(array) / sizeof(int));
// push_front / pop_front / push_back / pop_back
L.push_front(6);
L.push_back(6);
Print(L);
L.pop_front();
L.pop_back();
Print(L);
}
2、empalce_back / emplace_front / emplace
void ListModifiersTest() {
//emplace_back / emplace_front / empalce
list l;
Date d(2018, 1, 1);
l.push_back(d);
l.emplace_back(2012, 12, 12);
l.emplace_front(2019, 12, 12);
}
3、insert / erase
void ListModifiersTest() {
//insert / erase
int array[] = { 1, 2, 3};
list L1(array, array + sizeof(array) / sizeof(int));
//获取链表的第二个结点
auto pos = ++L1.begin();
cout << *pos << endl;
//在pos的前面插入4
L1.insert(pos, 4);
Print(L1);
//在pos的前插入4个5
L1.insert(pos, 4, 5);
Print(L1);
//在pos前面插入[v.begin(),v.end())区间中的的元素
vector v{9,5,2,7};
L1.insert(pos, v.begin(), v.end());
Print(L1);
//删除pos位置的元素
L1.erase(pos);
Print(L1);
//删除list 中[begin,end)区间的中的所有元素
L1.erase(L1.begin(), L1.end());
Print(L1);
}
4、resize / swap / clear
void Test() {
int array[] = { 1, 2, 3 };
list L(array, array + sizeof(array) / sizeof(int));
Print(L);
//L的元素增加为10个,多余的默认值填充
L.resize(10);
Print(L);
//L的元素增加为20个,多余的用1填充
L.resize(20, 1);
Print(L);
//L的元素减少到5个
L.resize(5);
Print(L);
//用vector中的元素来构造list
vector v{ 9,5,2,7 };
list ll(v.begin(), v.end());
Print(ll);
//交换L和ll
L.swap(ll);
Print(L);
Print(ll);
//清空ll
Print(ll);
}
迭代器失效即迭代器所指向的节点的无效,即该节点被删除。因为list 的底层结构均为带头节点的双向链表结构,因此在list 中插入时是不会导致list 的迭代器失效的,只有删除的时候才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响;
void ListIteratorError() {
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
list ll(array, array + sizeof(array) / sizeof(int));
auto it = ll.begin();
while (it != ll.end()) {
ll.erase(it);
++it;
}
}
注:erase()执行后,it 所指向的节点已经删除,因此 it 无效,在下一次使用 it 时,必须先给其赋值;
vector 和 list 都时 STL 中非常重要的序列式容器,由于两个容器的底层结构不同,导致其特性以及应用场景不同;
有点长。。。
#include
using namespace std;
namespace My {
template
struct ListNode{
ListNode(const T& val = T())
:_pPre(nullptr)
, _pNext(nullptr)
, _val(nullptr)
{}
ListNode* _pPre;
ListNode* _pNext;
T _val;
};
//正向迭代器
template
class ListIterator {
typedef ListNode* PNode;
typedef ListIterator Self;
public:
ListIterator(PNode pNode = nullptr)
:_pNode(pNode)
{}
ListIterator(const Self& l)
:_pNode(l._pNode)
{}
T* operator*() {
return _pNode->_val;
}
T* operator->() {
return &(operator*());
}
Self& operator++() {
_pNode = _pNode->_pNext;
return *this;
}
Self& operator++(int) {
Self temp(*this);
_pNode = _pNode->_pNext;
return temp;
}
bool operator==(const Self& l) {
return _pNode == l._pNode;
}
bool operator!=(const Self& l) {
return _pNode != l._pNode;
}
PNode _pNode;
};
//反向迭代器
template
class ListReverseIterator {
typedef ListReverseIterator Self;
public:
ListReverseIterator(const Iterator& it)
:_it(it)
{}
ListReverseIterator(const Self& l)
:_it(l._it)
{}
Ref operator*() {
Iterator temp = _it;
return *(--temp);
}
Ref operator->() {
return &operator*();
}
Self& operator++() {
--_it;
return *this;
}
Self operator++() {
Iterator temp(_it);
--_it;
return temp;
}
Self& operator--() {
++_it;
return *this;
}
Self operator--() {
iterator temp(_it);
++_it;
return temp;
}
bool operator!=(const Self& s) {
return _it != s._it;
}
bool operator==(const Self& s) {
return _it == s._it;
}
private:
Iterator _it;
};
template
class List {
typedef ListIterator Iterator;
typedef ListIterator ConstIterator;
typedef ListReverseIterator ReverseIterator;
typedef ListReverseIterator ConstReveresIterator;
public:
//构造
List() {
CreateHead();
}
List(int n ,const T& value = T()) {
CreateHead();
for (int i = 0; i < n;++i) {
PushBack(value);
}
}
template
List(Iterator first,Iterator last) {
CreateHead();
while (first!=last) {
PushBack(*first);
++first;
}
}
List(const List& l) {
CreateHead();
List temp(l.CBegin(), l.CEnd());
this->Swap(temp);
}
List& operator=(const List& l) {
if (this != &l) {
List temp(l);
this->Swap(temp);
}
return *this;
}
~List() {
Clear();
delete _PHead;
_PHead = nullptr;
}
/* List Itreator */
Iterator Begin() {
return Iterator(_PHead->_pNext);
}
Iterator End() {
return Iterator(_PHead);
}
ReverseIterator RBegin() {
return ReverseIterator(End());
}
ReverseIterator REnd() {
return ReverseIterator(Begin());
}
ConstIterator CBegin() {
return ConstIterator(_PHead->_pNext);
}
ConstIterator CEnd() {
return ConstIterator(_PHead);
}
ConstReveresIterator CRBegin() {
return ConstReveresIterator(CEnd());
}
ConstReveresIterator CREnd() {
return ConstReveresIterator(CBegin());
}
/* List Capacity */
size_t Size()const {
size_t count = 0;
PNode pCur = _PHead->_pNext;
while (pCur != _PHead) {
++count;
pCur = pCur->_pNext;
}
return count;
}
bool Empty() {
return _PHead->_pNext == _PHead;
}
void Resize(size_t newSize,const T& val = T()) {
size_t oldSize = Size();
if (oldSize <= newSize) {
for (size_t i = oldSize; i < newSize; ++i)
PushBack(val);
}
else {
for (size_t i = newSize; i < oldSize; ++i)
PopBack(val);
}
}
/* List Access */
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 Modify */
void PushBack(const T& val) {
PNode pNewNdoe = new Node(val);
pNewNdoe->_pNext = _PHead;
pNewNdoe->_pPre = _PHead->_pPre;
_PHead->_pPre = pNewNdoe;
pNewNdoe->_pPre->_pNext = pNewNdoe;
}
void PopBack() {
PNode pDel = _PHead->_pPre;
if (pDel != _PHead) {
_PHead->_pPre = pDel->_pPre;
pDel->_pPre->_pNext = _PHead;
delete pDel;
}
}
void PushFront(const T& val) {
PNode pNewNode = new Node(val);
pNewNode->_pNext = _PHead->_pNext;
pNewNode->_pPre = _PHead;
_PHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
void PopFront() {
PNode PDel = _PHead->_pNext;
if (PDel != _PHead) {
_PHead->_pNext = PDel->_pNext;
PDel->_pNext->_pPre = _PHead;
delete PDel;
}
}
Iterator Inerst(Iterator pos,const T& val) {
PNode pNewNode = new Node(val);
PNode pCur = pos._pNode;
pNewNode->_pPre = pCur->_pPre;
pNewNode->_pNext = pCur;
pNewNode->_pPre->_pNext = pNewNode;
pCur->_pPre = pNewNode;
return iterator(pNewNode);
}
Iterator Erase(Iterator pos) {
PNode pDel = pos._pNode;
PNode pRet = pDel->_pNext;
pDel->_pPre->_pNext = pDel->_pNext;
pDel->_pNext->_pPre = pDel->_pPre;
delete pDel;
return Iterator(pRet);
}
void Clear() {
PNode pCur = _PHead->_pNext;
while (pCur != _PHead) {
_PHead->_pNext = pCur->_pNext;
delete pCur;
pCur = _PHead->_pNext;
}
_PHead->_pNext = _PHead;
_PHead->_pPre = _PHead;
}
void Swap(List& l) {
swap(_PHead,l._PHead);
}
private:
void CreateHead() {
_PHead = new Node;
_PHead->_pPre = _PHead;
_PHead->_pNext = _PHead;
}
private:
PNode _PHead;
};
}