C++ list容器详解

本文详细介绍了C++ STL中的list容器,包括其基本概念、链表的特点、优缺点以及迭代器的特性。接着,通过实例展示了list的构造函数、赋值与交换、大小操作、插入与删除、数据存取、反转与排序等功能,并提供了排序案例。此外,还演示了如何对自定义数据类型进行排序。
摘要由CSDN通过智能技术生成

list容器的基本概念

概念:list一种将数据进行链式存储的数据结构,被称为链表

链表:是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:链表由一系列结点组成
结点的组成:由一个存储数据元素的数据域和一个存储下一个结点地址的指针域组成

优点:

  1. 可以在任意位置快速插入和删除元素
  2. 采用动态存储分配,不会造成内存浪费和溢出

缺点:

  1. 占用空间比数组大
  2. 访问元素效率低,需要遍历链表才能访问元素

迭代器:

  1. 链表的存储方式不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
  2. 插入和删除操作都不会造成原有的迭代器失效 , 这在vector中不成立,因为vector的动态扩容机制会改变原有数据的存储地址,地址改变了,迭代器自然失效了

注意:

  1. STL中的list容器是一个双向循环链表
  2. 使用list容器需要包含头文件#include<list>

1.list的构造函数

 函数原型:
 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);
}

测试结果:
在这里插入图片描述

2.list的赋值和交换

 函数原型:
 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);
}

测试结果:
在这里插入图片描述

3.list的大小操作

 函数原型:
 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);
}

测试结果:
在这里插入图片描述

4.list的插入和删除

 函数原型:
 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);
}

测试结果:
在这里插入图片描述

5.list的数据存取

 函数原型:
 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;
}

测试结果:
在这里插入图片描述

6.list的反转与排序

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);
}

测试结果:
在这里插入图片描述

7.list的排序案例

案例描述:将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);
}

测试结果:
在这里插入图片描述

  • 19
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

&不逝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值