目录
一、list的概念理解
list链表是将数据元素进行链式存储,在物理单元上是非连续的结构,与vector动态数组不同,数组是一片连续的内存空间,list链表是由一系列节点组成,而节点是由一个存储数据元素的数据域和一个存储上一个节点地址以及下一个节点地址的指针域组成,数据元素的逻辑顺序是通过链表的每一节点的元素指针链接实现的,在STL中的list链表是一个双向循环的链表。
1、链表中每个节点都由数据元素和prev、next指针组成;
2、prev指针指向前一个节点的地址,next指针指向下一个节点地址;
3、当当前节点是首节点时,可以让prev指针为空或者指向最后一个节点的地址;
4、当当前节点时末节点时,可以让next指针为空或者指向首节点的地址;
这就是list双向循环链表,迭代器不支持随机访问,只允许迭代器自加或者自减的操作,访问弱于vector等容器。
二、构造函数
list构造函数与vector、deque动态数组一样,差别不大。
(1)list<T> list_test:默认构造函数,也叫无参构造函数;
(2)list<T> list_test(begin, end):带有迭代器区间的构造函数,区间是[begin,end);
(3)list<T> list_test(n,element):n个相同元素element的构造函数;
(4)List<T> list_test(const list<T>& List):拷贝构造函数。
//! 构造函数
void ConstructorTest()
{
// 无参构造(默认构造)
list<int> list1;
list1.push_back(100);
list1.push_back(200);
list1.push_front(20);
list1.push_front(10);
PrintflnList(list1);
// 带迭代器的默认构造
list<int> list2(list1.begin(), list1.end());
PrintflnList(list2);
// N个相同元素的构造
list<int> list3(10, 666);
PrintflnList(list3);
// 拷贝构造
list<int> list4(list3);
PrintflnList(list4);
}
三、元素插入和删除
(1)push_front( element ):在链表头部加入一个元素element;
(2)pop_front():移除链表头部第一个元素;
(3)push_back( element ):在链表尾部加入一个元素element;
(4)pop_back():移除链表尾部最后一个元素;
(5)insert( pos,element ):在链表的pos位置(迭代器)插入一个元素element,返回值为新元素的pos位置;
(6)insert( pos,n,element ):在链表的pos位置(迭代器)插入n个相同的元素element,无返回值;
(7)insert( pos, begin, end ):在链表的pos位置(迭代器)插入一个链表的迭代器区间[begin,end),无返回值 ;
(8)erase( pos ):删除链表pos位置的元素,返回下一个元素的位置;
(9)erase( begin, end ):删除链表[begin,end)区间的元素,返回下一个元素的位置;
(10)clear():清空链表的元素;
(11)remove( element ):删除链表中所有与element相匹配的元素,该不是迭代器,只是元素的值本身。
//! 插入和删除
void InsertDelete()
{
list<int> list_test;
// 头部插入
list_test.push_front(30);
list_test.push_front(20);
list_test.push_front(10);
// 尾部插入
list_test.push_back(100);
list_test.push_back(200);
list_test.push_back(300);
PrintflnList(list_test);
// 删除头部元素
list_test.pop_front();
PrintflnList(list_test);
// 删除尾部元素
list_test.pop_back();
PrintflnList(list_test);
// insert在pos位置插入elem
list<int>::iterator it = list_test.begin();
list_test.insert(++it, 666);
PrintflnList(list_test);
// insert在pos位置插入n个相同的elem
list_test.insert(list_test.begin(), 3, 1000);
PrintflnList(list_test);
// insert在pos位置插入[begin,end)的元素
list<int> list1;
list1.insert(list1.begin(), list_test.begin(), list_test.end());
PrintflnList(list1);
// erase删除pos上的元素
list1.erase(list1.begin());
PrintflnList(list1);
// erase删除[begin,end)的元素
// 当区间为整个链表的迭代器区间,则等价于clear清空操作,就不演示clear()操作了
list1.erase(list1.begin(), list1.end());
PrintflnList(list1);
// remove移除匹配有关的元素
list_test.remove(100);
PrintflnList(list_test);
}
四、数据存取
(1)front():返回链表的第一个元素;
(2)back():返回链表的最后一个元素;
值得注意的是在STL中,list是不支持[ ]和at()的方式去访问链表中的元素,list的本质是双向循环链表,并非一段连续的线性存储空间存储数据。
// 数据存取
void DataAccess()
{
list<int> list_test;
list_test.push_back(100);
list_test.push_back(200);
list_test.push_back(300);
qDebug() << "链表第一个元素: " << list_test.front();
qDebug() << "链表最后一个元素: " << list_test.back();
}
五、大小操作
(1)empty():判断list容器是否为空;
(2)size():返回元素个数;
(3)resize( size ):重新指定容器大小为size;
(4)resize( size, elem ):重新指定容器大小为size,并以elem填充新增数据元素。
// 大小操作
void SizeTest()
{
list<int> list_test;
list_test.push_back(100);
list_test.push_back(200);
list_test.push_back(300);
PrintflnList(list_test);
if( !list_test.empty() )
{
qDebug() << "list容器大小: " << list_test.size();
list_test.resize(5);
PrintflnList(list_test);
list_test.resize(10, 666);
PrintflnList(list_test);
}
}
六、反转和排序
(1)reverse():list容器元素反转,即元素位置收尾调换,该接口为list的成员函数;
(2)sort():list容器元素排序,默认排序顺序是升序;
(3)sort<_Pr2>( _Pr2 _Pred ): list成员函数sort的重载函数,参数可以是一个自定义函数或者仿函数,除默认排序外,其他自定义排序需要利用该函数进行实现,很奇怪的是我在Qt环境编译时是没有该接口的,不知道是不是每个编译器厂商的编译器标准不一样。
// 反转和排序
void ReverseSortTest()
{
list<int> list_test;
list_test.push_back(66);
list_test.push_back(100);
list_test.push_back(88);
list_test.push_back(18);
qDebug() << "反转前: ";
PrintflnList(list_test);
list_test.reverse();
qDebug() << "反转后: ";
PrintflnList(list_test);
list_test.sort();
qDebug() << " 默认排序后: ";
PrintflnList(list_test);
}
在VS中试了下自定义的降序操作,是可以的行得通的:
bool MySort(int value1, int value2)
{
return (value1 > value2);
}
void SortTest()
{
list<int> L;
L.push_back(300);
L.push_back(100);
L.push_back(400);
L.sort(MySort);
PrintflnList(L);
}