list
基本概念及结构
功能:将数据进行链式存储
链表由一个个结点组成 结点由数据域和指针域组成 数据域存放当前位置的数据 指针域维护下一个结点数据域的地址
链表的优缺点
优点 :
采用动态储存分配,不会造成内存浪费和溢出
可以对任意位置进行快速插入或删除元素
插入时 将新结点的指针域指向下一结点的数据域地址,其前一节点的指针域指向新结点的数据域地址即可,不用移动其他位置上的数据
缺点:
容器遍历速度没有数组快,需要找指针域进行遍历,且占用的空间大于数组
list有一个重要的特性,插入操作和删除操作都不会造成原有list迭代器失效,这在vector是不成立的
STL中的链表结构
STL中的链表是一个双向循环链表 指针域存放的指针有两个,为前一结点的指针域和后一节点的指针域
图中并没有进行循环 第一个结点指针域中prev指针指向最后一个结点的数据域 而最后一个结点的next指针指向第一关结点的数据域
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
默认构造
list<T> lst; //list采用采用模板类实现,对象的默认构造形式:
list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem); //构造函数将n个elem拷贝给本身。
list(const list &lst); //拷贝构造函数。
示例
//list容器的构造函数
void test01() {
list<int>L1;//创建list容器
L1.push_back(10);//添加数据
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2(L1.begin(), L1.end());//区域方式构造
list<int>L3(L2);//拷贝构造
list<int>L4(4,100);//n个elem构造
}
赋值和交换操作
assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem); //将n个elem拷贝赋值给本身。
list& operator=(const list &lst); //重载等号操作符
swap(lst); //将lst与本身的元素互换。
示例
void test01() {
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2 = L1;
list<int>L3;
L3.assign(L2.begin(), L2.end());
list<int>L4;
L4.assign(10, 100);
list<int>L5;
L1.swap(L5);
}
大小操作
size(); //返回容器中元素的个数
empty(); //判断容器是否为空
resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
resize(num, elem);重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
如果容器变短,则末尾超出容器长度的元素被删除。
示例
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
if (L1.empty())
{
cout << "L1为空" << endl;
}
else
{
cout << "L1不为空" << endl;
cout << "L1的大小为: " << L1.size() << endl;
}
//重新指定大小
L1.resize(10);
L1.resize(15,100);
}
插入和删除
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素。
示例
void test01()
{
list<int> L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
//尾删
L.pop_back();
//头删
L.pop_front();
//插入
list<int>::iterator it = L.begin();
L.insert(++it, 1000);
//删除
it = L.begin();
L.erase(++it);
//移除
L.push_back(10000);
L.remove(10000);//会将链表里所有10000移除
//清空
L.clear();
printList(L);
}
尾插 — push_back 尾删 — pop_back 头插 — push_front 头删 — pop_front
插入 — insert 删除 — erase 移除 — remove 清空 — clear
数据存取
front(); //返回第一个元素
back(); //返回最后一个元素
list不支持[]和at的访问原因:
list本质是链表,不是连续的线性空间存储数据,迭代器也不支持随机访问
list<int>::iterator it = L.begin();
it = it + 2; //错误,不可以随机访问
it ++ ; //正确,支持双向
反转和排序
reverse();//反转
sort();//排序
bool myCompare(int val1 , int val2)
{
return val1 > val2;
}
//反转和排序
void test01()
{
list<int> L;
L.push_back(90);
L.push_back(30);
L.push_back(20);
L.push_back(70);
printList(L);
//反转容器的元素
L.reverse();//倒序输出
printList(L);
//排序
L.sort(); //默认的排序规则 从小到大
printList(L);
L.sort(myCompare); //指定规则,从大到小
printList(L);
}
排序的案例
#include<iostream>
#include<cstring>
#include<algorithm>
#include<list>
using namespace std;
class player {
public:
player(string name, int age, int high) {
this->name = name;
this->age = age;
this->high = high;
}
string name;
int age;
int high;
void printff() {
cout << "姓名:" << this->name << "年纪:" << this->age << "身高:" << this->high << endl;
}
};
void print(list<player>& L) {
for (list<player>::iterator it = L.begin(); it != L.end(); it++) {
it->printff();
}
}
//自己写的 麻烦了
//bool antt(const player& p1, const player& p2) {
// if (p1.age < p2.age) {
// return true;
// }
// else if (p1.age > p2.age) {
// return false;
// }
// else {
// if (p1.high < p2.high)
// return true;
// else
// return false;
// }
//}
bool antt(const player& p1, const player& p2) {
if (p1.age == p2.age) {
return p1.high < p2.high;
}
return p1.age < p2.age;
}
void test01() {
player p1("小赵", 18, 180);
player p2("大牛", 27, 170);
player p3("林五", 19, 181);
player p4("赵武", 18, 167);
player p5("马九", 16, 178);
list<player>L;
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
cout << "排序前:" << endl;
print(L);
L.sort(antt);
cout << "------------------------------------------------------" << endl;
cout << "排序后:" << endl;
print(L);
}
int main() {
test01();
}