(1)list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
(2)list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
(3)list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
(4)与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
(5)与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)
方法一:
#include
#include
using namespace std;
void main()
{
list<int> mylist;
for (const auto &e : mylist)
{
cout << e << " ";
}
cout << endl;
}
方法二
#include
#include
using namespace std;
void main()
{
list<int> mylist;
list<int>::iterator it = mylist.begin();
while (it != mylist.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
如上几个函数的使用:
(1)构造n个val值(若未给默认是0)
#include
#include
using namespace std;
void main()
{
list<int> mylist(10,5);
list<int>::iterator it = mylist.begin();
cout << "head-->";
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end"<<endl;
}
#include
#include
using namespace std;
void main()
{
list<int> mylist(10, 5);
//拷贝构造
list<int> youlist = mylist;
list<int>::iterator it = youlist.begin();
cout << "head-->";
while (it != youlist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
}
(3)用一个区间的数据构造(包含区间左边,不包含区间右边,[ ))
#include
#include
using namespace std;
void main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
//是一个左闭右开的区间[ )
list<int> mylist(arr,arr+n);
list<int>::iterator it = mylist.begin();
cout << "head-->";
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end"<<endl;
}
#include
#include
using namespace std;
void main()
{
list<int> mylist(10,5);
//通过迭代器区间构造
list<int> youlist(mylist.begin(),mylist.end());
list<int>::iterator it = youlist.begin();
cout << "head-->";
while (it != youlist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
}
对比使用如下:
#include
#include
using namespace std;
void main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
list<int> mylist(arr,arr+n);
//正向迭代器
list<int>::iterator it = mylist.begin();
cout << "head-->";
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end"<<endl;
//反向迭代器
list<int>::reverse_iterator rit = mylist.rbegin();
cout << "head-->";
while (rit != mylist.rend())
{
cout << *rit << "-->";
++rit;
}
cout << "end" << endl;
}
#include
#include
using namespace std;
void main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
list<int> mylist(arr, arr + n);
//判空
cout << "empty = " << mylist.empty() << endl;
//求链表元素个数
cout << "size = " << mylist.size() << endl;
}
#include
#include
using namespace std;
void main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
list<int> mylist(arr, arr + n);
//访问头尾节点
cout << "oldfront = " << mylist.front() << endl;
cout << "oldback = " << mylist.back() << endl;
//修改头尾节点
mylist.front() = 999;
mylist.back() = 444;
cout << "newfront = " << mylist.front() << endl;
cout << "newback = " << mylist.back() << endl;
list<int>::iterator it = mylist.begin();
cout << "head-->";
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
}
#include
#include
using namespace std;
void main()
{
list<int> mylist;
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);
//尾插
mylist.push_back(1);
mylist.push_back(2);
mylist.push_back(3);
mylist.push_back(4);
mylist.push_back(5);
//头插
mylist.push_front(0);
//在pos位置插入val
list<int>::iterator pos = find(mylist.begin(), mylist.end(), 3);
mylist.insert(pos, 99);
//删除pos位置的值
/*mylist.erase(pos);*/
//插入n个值
/*mylist.insert(pos, 5, 333);*/
//插入一个区间
/*mylist.insert(pos, arr, arr + 3);*/
list<int>::iterator it = mylist.begin();
while(it != mylist.end())
{
cout << *it <<"-->";
++it;
}
cout << "end" << endl;
}
链表的交换
#include
#include
using namespace std;
void main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
list<int> mylist(arr,arr+5);
list<int> youlist(arr + 5, arr + 10);
cout << "交换前:" << endl;
list<int>::iterator it = mylist.begin();
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
list<int>::iterator yit = youlist.begin();
while (yit != youlist.end())
{
cout << *yit << "-->";
++yit;
}
cout << "end" << endl;
//交换两个链表
mylist.swap(youlist);
cout << "交换后:" << endl;
it = mylist.begin();
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
yit = youlist.begin();
while (yit != youlist.end())
{
cout << *yit << "-->";
++yit;
}
cout << "end" << endl;
}
#include
#include
#include
using namespace std;
void main()
{
int arr[] = { 1, 9, 4, 2, 5, 10, 6, 7,3, 8};
int n = sizeof(arr) / sizeof(arr[0]);
list<int> mylist(arr, arr + n);
list<int>::iterator it = mylist.begin();
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
//从小到大排序
mylist.sort();
it = mylist.begin();
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
//从大到小排序
mylist.sort(greater<int>());
it = mylist.begin();
while (it != mylist.end())
{
cout << *it << "-->";
++it;
}
cout << "end" << endl;
}
迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
举例如下:
如上图所示,删除迭代器it所指向的节点,此时迭代器已经失效,不能再对迭代器操作,虽然迭代器 it 失效,但是不会影响其他迭代器,如下图所示 it1 可以正常访问
删除节点的返回值是删除节点的下一个节点的迭代器
例题:如下代码可以正常运行吗?
#include
#include
using namespace std;
void TestListIterator1()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> l(array, array + sizeof(array) / sizeof(array[0]));
auto it = l.begin();
while (it != l.end())
{
l.erase(it);
++it;
}
}
void main()
{
TestListIterator1();
}
如上代码肯定是不能运行的,因为erase()函数执行之后,it所指向的节点已被删除,删除之后迭代器已经失效,不能在对迭代器操作,应接收erase()的返回值,修改如下:
#include
#include
using namespace std;
void TestListIterator1()
{
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> l(array, array + sizeof(array) / sizeof(array[0]));
auto it = l.begin();
while (it != l.end())
{
//it不需要++,删除节点的返回值是删除节点的下一个节点的迭代器
it = l.erase(it);
}
}
void main()
{
TestListIterator1();
}
#include
#include
using namespace std;
namespace MyList
{
template<class _Ty>
class List;
template<class _Ty>
class ListIterator;
//节点类
template<class _Ty>
class ListNode
{
friend class List<_Ty>;
friend class ListIterator<_Ty>;
public:
//节点的构造函数
ListNode() :_Value(_Ty()), _Next(nullptr), _Prev(nullptr)
{}
ListNode(_Ty Val, ListNode* next = nullptr, ListNode* prev = nullptr) :_Value(Val), _Next(next), _Prev(prev)
{}
//节点的析构函数
~ListNode()
{}
private:
_Ty _Value;
ListNode* _Next;
ListNode* _Prev;
};
//迭代器类
template<class _Ty>
class ListIterator
{
typedef ListIterator _It;
public:
//迭代器的构造
ListIterator() :_Ptr(nullptr)
{}
ListIterator(ListNode<_Ty>* _P) :_Ptr(_P)
{}
public:
bool operator!=(const _It &it)
{
return _Ptr != it._Ptr;
}
bool operator==(const _It &it)
{
return _Ptr == it._Ptr;
}
_Ty& operator*()
{
return (_Ptr->_Value);
}
_It& operator++()
{
_Ptr = _Ptr->_Next;
return *this;
}
public:
ListNode<_Ty>* _MyNode()
{
return _Ptr;
}
public:
_It& operator--()
{
_Ptr = _Ptr->_Prev;
return *this;
}
private:
ListNode<_Ty>* _Ptr;
};
//链表类
template<class _Ty>
class List
{
public:
typedef ListNode<_Ty>* _Nodeptr;
typedef ListIterator<_Ty> iterator;
public:
//求节点个数
size_t size()const
{
return _Size;
}
//判空
bool empty()const
{
return (size() == 0);
}
public:
//迭代器
iterator begin()
{
return iterator(_Head->_Next);
}
iterator end()
{
return iterator(_Head);
}
public:
//插入
iterator insert(iterator pos, const _Ty &x)
{
_Nodeptr cur = pos._MyNode();
_Nodeptr _S = new ListNode<_Ty>(x);
_S->_Next = cur;
_S->_Prev = cur->_Prev;
_S->_Next->_Prev = _S;
_S->_Prev->_Next = _S;
++_Size;
return iterator(_S);
}
//在pos位置插入n个x,
void insert(iterator pos, size_t n, const _Ty &x)
{
while (n--)
{
insert(pos, x);
}
}
public:
//尾插
iterator push_back(const _Ty &x)
{
return insert(end(), x);
}
//头插
iterator push_front(const _Ty &x)
{
return insert(begin(), x);
}
public:
//删除pos位置的节点,返回该节点的下一个位置
iterator erase(iterator pos)
{
_Nodeptr cur = pos._MyNode();
_Nodeptr next_node = cur->_Next;
cur->_Prev->_Next = cur->_Next;
cur->_Next->_Prev = cur->_Prev;
delete cur;
_Size--;
return iterator(next_node);
}
public:
//删除一个区间
iterator erase(iterator first, iterator last)
{
while (first != last)
{
first = erase(first);
}
return first;
}
//清除
void clear()
{
erase(begin(), end());
}
public:
//尾删
iterator pop_back()
{
return erase(--end());
}
//头删
iterator pop_front()
{
return erase(begin());
}
public:
//求头节点
_Ty & Front()
{
return *begin();
}
const _Ty & Front()const
{
return *begin();
}
//求尾节点
_Ty & Back()
{
return *--end();
}
const _Ty & Back()const
{
return *--end();
}
public:
//交换函数
void swap(List<_Ty> & lt)
{
//用系统里的交换函数
std::swap(_Head, lt._Head);
std::swap(_Size, lt._Size);
}
public:
//List的构造函数
List() :_Head(BuyNode()), _Size(0)
{}
List(size_t n, const _Ty & x = _Ty()) :_Size(0)
{
_Head = BuyNode();
insert(end(), n, x);
}
List(const _Ty *first, const _Ty *last) :_Size(0)
{
_Head = BuyNode();
while (first != last)
{
push_back(*first++);
}
}
List(iterator first,iterator last) :_Size(0)
{
_Head = BuyNode();
while (first != last)
{
push_back(*first);
++first;
}
}
//List的拷贝构造函数
List(List<_Ty> & lt) :_Size(0)
{
_Head = BuyNode();
List<_Ty> tem(lt.begin(), lt.end());
this->swap(tem);
}
//List的析构函数
~List()
{
clear();
delete _Head;
_Size = 0;
}
protected:
//申请一个节点
_Nodeptr BuyNode()
{
_Nodeptr _S = new ListNode<_Ty>;
_S->_Prev = _S->_Next = _S;
return _S;
}
private:
_Nodeptr _Head;
size_t _Size;
};
}
void main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7,8, 9 ,10};
MyList::List<int> lt(arr,arr+5);
MyList::List<int> lt1(lt);
/*MyList::List lt1(arr+5, arr + 10);*/
//lt.swap(lt1);
//MyList::List lt(10);
//MyList::List lt(10,5);
lt.insert(lt.end(), 0);
lt.insert(lt.end(), 1);
lt.insert(lt.end(), 2);
lt.insert(lt.end(), 3);
lt.insert(lt.end(), 4);
lt.insert(lt.end(), 5);
//lt.push_back(6);
//lt.push_front(-1);
//lt.erase(lt.begin());
//lt.erase(--lt.end());
//lt.pop_back();
//lt.pop_front();
MyList::List<int>::iterator it = lt.begin();
while (it != lt.end())
{
cout << *it << " ";
++it;
}
cout << endl;
MyList::List<int>::iterator it1 = lt1.begin();
while (it1 != lt1.end())
{
cout << *it1 << " ";
++it1;
}
cout << endl;
//cout << lt.Back() << endl;
//cout << lt.Front() << endl;
}