C++进阶-STL list容器的简单认识

STL list容器的简单认识

    • list容器基本概念
    • list容器构造函数
    • list容器赋值和交换
    • list容器大小操作
    • list容器插入和删除
    • list容器数据存取
    • list容器反转和排序
        • list排序案例

list容器基本概念

list容器是将数据进行链式存储的容器,链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的

链表的组成:链表由一系列节点组成

节点的组成:一个是存放数据元素的数据域,另一个是存储下一个结点地址的指针域

链表的优点:可以对任意位置进行快速的插入或删除元素
缺点:容器的遍历速度没有数组快,占用的空间比数组大

STL中的链表是一个双向循环链表

C++进阶-STL list容器的简单认识_第1张图片
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

list的优点:

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
    list的缺点:
  • 链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大

list有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的

list容器构造函数

  • list lit; 默认构造函数
list<int> lst;
  • list(beg, end); 构造函数将[beg, end)中的元素拷贝给本身
list<int> lst;
list<int> lst_2(lst.begin(), lst.end());
  • list(n, elem); 构造函数将n个elem拷贝给本身
list<int> lst(3, 12);
  • list(const list* list); 拷贝构造函数
list<int> lst;
list<int> lst_2(lst);

list容器赋值和交换

  • assign(beg, end); 将[beg, end)区间中的数据拷贝赋值给本身
list<int> lst;
list<int> lst2;
lst2.assign(lst.begin(), lst.end());
  • assign(n, elem); 将n个elem拷贝赋值给本身
list<int> lst2;
lst2.assign(3, 12);
  • list& operator=(const list& lst); 重载等号运算符
list<int> lst;
list<int> lst2;
lst2 = lst;
  • swap(lst); 将lst与本身的元素互换
list<int> lst;
lst.push_back(12);
lst.push_back(13);
list<int> lst2;
lst2.push_back(14);
lst2.push_back(15);
lst2.swap(lst);
for (list<int>::iterator it = lst.begin(); it != lst.end(); it++)
{
	std::cout << *it << " ";
}
std::cout << std::endl;
for (list<int>::iterator it = lst2.begin(); it != lst2.end(); it++)
{
	std::cout << *it << " ";
}

list容器大小操作

  • size(); 返回容器中元素的个数
lis.size();
  • empty(); 判断容器是否为空
lis.empty();
  • resize(num); 重新指定容器长度为num,容器变长,默认值填充之,容器变短,元素删除之
lis.resize(20);
  • resize(num, elem); 重新指定容器长度为num,容器变长,elem填充之,容器变短,元素删除之
lis.resize(20, 10);

list容器插入和删除

  • push_back(elem); 在容器尾部加入一个元素
list lst;
lst.push_back(12);
  • pop_back(); 删除容器尾部的一个元素
list lst;
lst.pop_back();
  • push_front(elem); 在容器头部插入一个元素
list lst;
lst.push_front(12);
  • pop_front(); 删除容器头部的一个元素
list lst;
lst.pop_front();
  • insert(pos, elem); 在pos位置插入elem元素的拷贝,返回新数据的位置
list lst;
lst.insert(lst.begin(), 100);
  • insert(pos, n, elem); 在pos位置插入n个elem元素的拷贝,无返回值
list lst;
lst.insert(lst.begin(), 10, 100);
  • insert(pos, beg, end); 在pos位置插入[beg, end)区间的数据,无返回值
list li;
list l2;
l2.insert(li.begin(), li.end());
  • clear(); 清空列表的数据
list ls;
ls.clear();
  • erase(beg, end); 删除[beg, end)区间的数据,返回下一个数据的位置
list ls;
ls.earse(ls.begin(), ls.end());
  • earse(pos); 删除pos位置的元素,返回下一个元素的位置
list ls;
ls.earse(ls.begin());
  • remove(elem); 删除容器中所有与elem元素匹配的元素
list ls;
ls.remove(12);

list容器数据存取

  • front(); 返回第一个元素
list<int> lst;
lst.push_back(10);
lst.push_back(20);
//返回第一个元素
std::cout << lst.front() << std::endl;
  • back(); 返回最后一个元素
list<int> lst;
lst.push_back(10);
lst.push_back(20);
std::cout << lst.back() << std::endl;

list容器反转和排序

  • reverse(); 反转链表
#include 
#include 
using namespace std;

void printf(const list<int>& lst)
{
	for (list<int>::const_iterator it = lst.begin(); it != lst.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
}

int main()
{
	list<int> lst;
	lst.push_back(10);
	lst.push_back(20);
	std::cout << "调用反转链表前:" << std::endl;
	printf(lst);
	lst.reverse();
	std::cout << "调用反转链表后:" << std::endl;
	printf(lst);
}

在这里插入图片描述

  • sort(); 链表排序
#include 
#include 
using namespace std;

void printf(const list<int>& lst)
{
	for (list<int>::const_iterator it = lst.begin(); it != lst.end(); it++)
	{
		std::cout << *it << " ";
	}
	std::cout << std::endl;
}

bool compare(int a, int b)
{
	//降序,第一个数大于第一个数
	return a > b;
}

int main()
{
	list<int> lst;
	lst.push_back(10);
	lst.push_back(30);
	lst.push_back(20);
	std::cout << "调用排序链表前:" << std::endl;
	printf(lst);
	lst.sort();
	std::cout << "调用排序链表后:" << std::endl;
	printf(lst);

	//使用自定义比较方法
	lst.sort(compare);

	std::cout << "调用自定义排序链表后:" << std::endl;
	printf(lst);
}

C++进阶-STL list容器的简单认识_第2张图片

所有不支持随机访问迭代器的容器不能使用标准排序算法,这些容器会内置排序算法

list排序案例

定义一个Person类,包含姓名、年龄、身高三个属性,最终打印结果按照年龄进行升序,年龄一致则按照身高降序排列

#include 
#include 
#include 
#include 
using namespace std;

class Person
{
private:
	string m_Name;
	int m_Age;
	float m_Height;

public:
	Person(string name, int age, float height)
	{
		this->m_Age = age;
		this->m_Height = height;
		this->m_Name = name;
	}
	int getAge()
	{
		return this->m_Age;
	}
	float getHeight()
	{
		return this->m_Height;
	}
	//常函数内部不能修改属性值,除非属性添加关键字mutable
	void printf() const
	{
		std::cout << this->m_Name << " 的年龄:" << this->m_Age << " 身高:" << this->m_Height << std::endl;
	}
	static bool compare(Person& front, Person& next)
	{
		if (front.getAge() < next.getAge())
		{
			return true;
		}
		if (front.getAge() == next.getAge()) {
			return front.getHeight() >= next.getHeight();
		}
		return false;
	}
};

void printfAll(const list<Person>& lst)
{
	for (list<Person>::const_iterator it = lst.begin(); it != lst.end(); it++)
	{
		//常对象只能调用常函数
		it->printf();
	}
}

int main()
{
	//随机数种子
	srand((unsigned int)time(NULL));
	string name_Str[] = { "张三","李四","王二","麻子" };
	list<Person> person_list;
	for (int i = 0; i < sizeof(name_Str) / sizeof(name_Str[0]); i++)
	{
		Person person(name_Str[i], rand() % 60 + 40, rand() % 150 + 40);
		person_list.push_back(person);
	}
	std::cout << "调用排序前,初始化的信息为:" << std::endl;
	printfAll(person_list);
	std::cout << "调用排序后,排序后的信息为:" << std::endl;
	person_list.sort(Person::compare);
	printfAll(person_list);
}

你可能感兴趣的:(C++入门与进阶内容专栏,c++,list,开发语言)