概念:list一种将数据进行链式存储的数据结构,被称为链表
链表:是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:链表由一系列结点组成
结点的组成:由一个存储数据元素的数据域和一个存储下一个结点地址的指针域组成
优点:
- 可以在任意位置快速插入和删除元素
- 采用动态存储分配,不会造成内存浪费和溢出
缺点:
- 占用空间比数组大
- 访问元素效率低,需要遍历链表才能访问元素
迭代器:
- 链表的存储方式不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
- 插入和删除操作都不会造成原有的迭代器失效 , 这在vector中不成立,因为vector的动态扩容机制会改变原有数据的存储地址,地址改变了,迭代器自然失效了
注意:
- STL中的list容器是一个双向循环链表
- 使用list容器需要包含头文件
#include
函数原型:
1.list<T> lst; //默认构造,list采用模板类实现
2.list(begin,end); //构造函数,利用迭代器实现区间赋值
3.list(n,elem); //构造函数,将n个elem赋值给本身
4.list(const list &lst); //拷贝构造
之后的测试中经常需要打印list,因此先定义一个打印输出的函数
void printList(const list<int>& lst)
{
cout << "打印list: ";
for (list<int>::const_iterator it = lst.begin(); it != lst.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
测试案例:
void text1()
{
list<int> lst1; //默认构造
for (int i = 1; i < 10; ++i)
{
lst1.push_back(i);
}
printList(lst1);
list<int> lst2(lst1.begin(), lst1.end()); //区间赋值的构造函数
printList(lst2);
list<int> lst3(9, 1); //将9个1赋值给本身
printList(lst3);
list<int> lst4(lst1); //拷贝构造
printList(lst3);
}
函数原型:
1.list& operator=(const list& lst); //重载赋值运算符
2.assign(begin,end); //利用迭代器实现区间赋值
3.assign(n,elem); //将n个elem赋值给本身
4.swap(lst); //将lst于本身互换
测试案例:
void text2()
{
list<int> lst1, lst2, lst3, lst4;
for (int i = 1; i < 10; ++i)
{
lst1.push_back(i);
}
printList(lst1);
lst2 = lst1; //重载的 = 赋值
printList(lst2);
lst3.assign(lst2.begin(), lst2.end()); //区间赋值
printList(lst3);
lst4.assign(9, 1); //将9个1赋值给本身
printList(lst4);
//list交换
lst1.swap(lst4);
cout << "交换后:" << endl;
printList(lst1);
printList(lst4);
}
函数原型:
1.size(); //返回容器中元素个数
2.empty(); //判断容器是否为空
3.resize(num); //重新指定容器长度,若变长,变长的部分赋值为0,
//若变短,超出容器长度的元素被删除
4.resize(num,elem); //重新指定容器长度,若变长,变长的部分赋值为elem
//若变短,超出容器长度的元素被删除
测试案例:
void text3()
{
list<int> lst1;
for (int i = 1; i < 10; ++i)
{
lst1.push_back(i);
}
printList(lst1);
if (!lst1.empty()) //容器若不为空
{
cout << "list容器的大小为:" << lst1.size() << endl;
}
cout << "重新指定长度,使容器变长: " << endl;
lst1.resize(15); //等价于lst1.resize(15,0);
printList(lst1);
cout << "重新指定长度,使容器变短: " << endl;
lst1.resize(5);
printList(lst1);
}
函数原型:
1.push_back(elem); //在容器尾部插入一个元素
2.push_front(elem); //在容器头部插入一个元素
3.pop_back(); //在容器尾部删除一个元素
4.pop_front(); //在容器头部删除一个元素
5.insert(pos,elem); //在迭代器pos处插入一个元素elem,返回新数据的位置
6.insert(pos,n,elem); //在迭代器pos处插入n个元素elem,无返回值
7.insert(pos,begin,end);//在迭代器pos处插入[begin,end)区间的数据,无返回值
8.clear(); //清除容器中所有数据
9.erase(begin,end); //删除[begin,end)区间的数据,返回下一个数据的位置
10.erase(pos); //删除迭代器pos处的数据,返回下一个数据的位置
11.remove(elem); //删除容器中所有等于elem的元素
测试案例:
void text4()
{
list<int> lst1;
for (int i = 1; i < 6; ++i)
{
lst1.push_back(i+5); //在容器尾部插入一个元素
lst1.push_front(6 - i); //在容器头部插入一个元素
}
printList(lst1);
lst1.pop_back(); //在容器尾部删除一个元素
lst1.pop_front(); //在容器尾部删除一个元素
printList(lst1);
list<int> lst2;
//在lst2头部插入lst1的全部数据
lst2.insert(lst2.begin(),lst1.begin(), lst1.end());
lst2.insert(lst2.end(), 5, 10); //在lst2尾部插入5个10
printList(lst2);
lst2.remove(10); //删除lst2中等于10的元素
printList(lst2);
//删除lst2中所有元素
lst2.erase(lst2.begin(), lst2.end()); //等价于lst2.clear();
printList(lst2);
}
函数原型:
1.front(); //返回容器第一个元素
2.back(); //返回容器最后一个元素
测试案例:
void text5()
{
list<int> lst1;
for (int i = 1; i < 10; ++i)
{
lst1.push_back(i);
}
printList(lst1);
cout << "容器中第一个元素是:" << lst1.front() << endl;
cout << "容器中最后一个元素是:" << lst1.back() << endl;
}
1.reverse(); //反转链表
2.sort(); //排序链表。注意这是一个成员函数,测试中会解释
测试案例:
void text6()
{
list<int> lst1;
lst1.push_back(5);
lst1.push_back(1);
lst1.push_back(7);
lst1.push_back(3);
lst1.push_back(6);
printList(lst1);
//反转
cout << "反转后:" << endl;
lst1.reverse();
printList(lst1);
//排序
//sort(lst1.begin(),lst1.end())//错误
//所有不支持随机访问迭代器的容器,不能使用标准算法
//但不支持随机访问迭代器的容器,内部会提供一些算法来弥补
lst1.sort(); //list容器内部的排序算法
printList(lst1);
}
案例描述:将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
排序规则:按照年龄进行升序排序,年龄相等时按照身高降序排序
测试案例:
class Person
{
public:
string m_name;
int m_age;
int m_hight;
Person(string name, int age, int hight)
{
m_name = name;
m_age = age;
m_hight = hight;
}
};
void printList(list<Person>& lst) //打印输出list容器中数据
{
for (list<Person>::iterator it = lst.begin(); it != lst.end(); it++)
{
cout << "姓名:" << (*it).m_name << " 年龄:" << (*it).m_age
<< " 身高:" << (*it).m_hight << endl;
}
}
bool comparePerson(Person p1,Person p2)//排序规则函数
{
if (p1.m_age == p2.m_age)
{
return p1.m_hight > p2.m_hight;
}
return p1.m_age < p2.m_age;
}
void text7()
{
list<Person> lst;
Person p1("王大", 45, 170);
Person p2("王二", 30, 175);
Person p3("张三", 30, 185);
Person p4("李四", 30, 170);
Person p5("王五", 25, 190);
Person p6("赵六", 20, 180);
lst.push_back(p1);
lst.push_back(p2);
lst.push_back(p3);
lst.push_back(p4);
lst.push_back(p5);
lst.push_back(p6);
printList(lst);
//按规则排序
cout << "-------------------------------" << endl;
cout << "排序后:" << endl;
lst.sort(comparePerson);
printList(lst);
}