小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
list
概念:
-
链表(
list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针连接实现的 -
链表的组成:链表是由一系列节点组成
-
节点的组成:一个是存储数据元素的数据域,另一个是存储下一个节点地址指针域
-
STL中的链表是一个双向循环链表 -
由于链表的存储方式并不是连续的内存空间,因此:链表
list中的迭代器只支持前移和后移,属于双向迭代器
优点:
-
链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大
-
list的一个重要性质:插入和删除操作都不会造成原有list迭代器的失效,这在vector中式不成立的
小结:
STL中list和vector是两个最常被使用的容器,各有优缺点
list构造函数
【函数原型】:
- list<T> lst; // list采用模板类实现,对象的默认构造形式
- list<begin,end>; //拷贝构造函数,将区间[begin,end]中的元素拷贝给自身
- list(n,elem); // 构造函数将n个elem拷贝给自身
- list(const list &lst); // 拷贝构造函数
【demo】:
#include <iostream>
#include <list>
using namespace std;
void printList(const list<int> &lst)
{
for (list<int>::const_iterator it = lst.begin(); it != lst.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list<int> l1;
l1.push_back(10);
l1.push_back(20);
l1.push_back(30);
l1.push_back(40);
cout << "默认构造函数:" << endl;
printList(l1);
list<int> l2(l1.begin(), l1.end());
cout << "拷贝[begin,end]区间的元素:" << endl;
printList(l2);
// 拷贝构造函数
list<int> l3(l2);
cout << "拷贝构造函数:" << endl;
printList(l3);
// 将10个1拷贝给自身
list<int> l4(10, 1);
cout << "将10个1拷贝给自身:" << endl;
printList(l4);
}
int main()
{
test01();
return 0;
}
list赋值和交换
【函数原型】:
- assign(begin,end); // 将[begin,end]区间中的数据拷贝赋值给自身
- assign(n,elem); //将n个ele拷贝赋值为自身
- list &operator=(const list &list); // 重载等号操作符
- swap(lst); // 将lst与自身的元素互换
【demo】:
#include <iostream>
#include <list>
using namespace std;
void printList(const list<int> &L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list<int> L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
cout << "L1:" << endl;
printList(L1);
list<int> L2;
L2.assign(L1.begin(), L1.end());
cout << "assign(begin,end); // 将[begin,end]区间中的数据拷贝赋值给自身 --> L2:" << endl;
printList(L2);
list<int> L3;
L3.assign(10, 1);
cout << "assign(n,elem); //将n个ele拷贝赋值为自身 --> L3:" << endl;
printList(L3);
list<int> L4 = L3;
cout << "list &operator=(const list &list); // 重载等号操作符 --> L4:" << endl;
printList(L4);
L3.swap(L1);
cout << "swap L1 and L3 :" << endl;
cout << "L1:";
printList(L1);
cout << "L3:";
printList(L3);
}
int main()
{
test01();
return 0;
}
list大小操作
【函数原型】:
- size(); // 返回容器中元素的个数
- empty(); // 判断容器是否为空
- resize(num); // 重新制定容器长度为num,若容器变长,则以默认值填充新位置,若容器变短,则末尾超出容器长度的部分将被删除
- resize(num,elem); // // 重新制定容器长度为num,若容器变长,则使用elem填充新位置,若容器变短,则末尾超出容器长度的部分将被删除
【demo】:
#include <iostream>
#include <list>
using namespace std;
void printList(const list<int> &L)
{
if (!L.empty())
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
else
{
cout << "list is empty !" << endl;
}
}
void test01()
{
list<int> L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
printList(L1);
cout << "L1.size() = " << L1.size() << endl;
L1.resize(10);
printList(L1);
L1.resize(20, 5);
printList(L1);
}
int main()
{
test01();
return 0;
}
list插入与删除
【函数原型】:
- push_back(elem); // 在容器尾部加入一个元素
- pop_back(); // 删除容器中最后一个元素
- push_front(); // 在容器开头插入一个元素
- pop_front(); // 删除容器开头的元素
- insert(pos,elem); // 在pos位置插入elem元素的拷贝,返回新数据的位置
- insert(pos,n,elem); // 在pos位置插入n个elem元素,无返回值
- insert(pos,begin,end); // 在pos位置插入[begin,end]区间的数据,无返回值
- clear(); // 清除所有数据
- erase(begin,end); // 删除[begin,end]区间内的数据,返回下一个数据的位置
- erase(pos); // 删除Pos位置的数据,返回下一个数据的位置
- remove(elem); // 删除容器中所有与elem匹配的元素
【demo】:
#include <iostream>
#include <list>
using namespace std;
void printList(const list<int> &L)
{
if (L.empty())
{
cout << "L is empty ." << endl;
}
else
{
cout << "L : ";
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << " , size:" << L.size() << endl;
}
}
void test01()
{
list<int> L1;
// 尾插
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
//头插
L1.push_front(100);
L1.push_front(200);
L1.push_front(300);
printList(L1);
// 尾删
L1.pop_back();
// 头删
L1.pop_front();
printList(L1);
list<int>::iterator it = L1.begin();
// 头插
L1.insert(++it, 1000);
printList(L1);
// 删除元素
it = L1.begin();
L1.erase(++it);
printList(L1);
//移除元素
L1.push_back(66666);
L1.push_back(88888);
printList(L1);
L1.remove(66666);
printList(L1);
L1.clear();
printList(L1);
}
int main()
{
test01();
return 0;
}
小结
-
尾插 push_back()
-
尾删 pop_back()
-
头插 push_front()
-
头删 pop_front()
-
插入 insert()
-
删除 erase()
-
移除 remove()
-
清空 clear()
list数据存取
【函数原型】:
- front(); // 返回第一个元素
- back(); // 返回最后一个元素
【demo】:
#include <iostream>
#include <list>
using namespace std;
void printList(const list<int> &L)
{
if (L.empty())
{
cout << "L is empty ." << endl;
}
else
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << " , size:" << L.size() << endl;
}
}
void test01()
{
list<int> L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
cout << "first elem is : " << L1.front() << endl;
cout << "last elem is : " << L1.back() << endl;
// list 不支持 at,[]操作
// list容器的迭代器是双向迭代器,不支持随机访问
list<int>::iterator it = L1.begin();
//it = it + 1; // 错误,不可以跳跃访问,即使是+1
}
int main()
{
test01();
return 0;
}
list反转与排序
【函数原型】:
- reverse(); //反转链表
- sort(); //链表排序
【demo】:
#include <iostream>
#include <list>
using namespace std;
void printList(const list<int> &L)
{
if (L.empty())
{
cout << "L is empty ." << endl;
}
else
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << " , size:" << L.size() << endl;
}
}
bool myCompare(int v1, int v2)
{
return v1 > v2;
}
void test01()
{
list<int> L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
// 反转容器中的元素
L1.reverse();
cout << "L1 after reverse : " << endl;
printList(L1);
// 默认排序
L1.sort();
cout << "L1 after default sort : " << endl;
printList(L1);
// 指定排序规则,从大到小
L1.sort(myCompare);
cout << "L1 after myCompare sort : " << endl;
printList(L1);
}
int main()
{
test01();
return 0;
}