C++STL list容器 数据存取 反转和排序 自定义数据类型排序案例 list成员函数sort高级排序

1 list 数据存取

功能描述: 对list容器中数据进行存取

函数原型:

  • front(); //返回第一个元素。
  • back(); //返回最后一个元素。

在之前的容器学习中,访问数据时都有[]和at(string、vector、deque可以)可以访问容器的元素。但是对于list而言,是没有[]和at访问数据的方式。因为list是链表结构,是由每个节点链式组成的,不能直接通过[]和at访问其中的节点的数据域。只能通过节点的指针域来访问下一个节点的数据。而且list迭代是双向迭代器,是不支持随机访问的。string、vector、deque可以通过[]和at访问元素。

代码示例:

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


void test1()
{
	int s = 45;
	list<int> L;
	L.push_back(25);
	L.push_back(26);
	L.push_back(27);
	L.push_front(28);
	L.push_front(29);
	L.push_front(30);

	//L[0]; 不可以用[]访问list容器的元素
	//L.at(0); 不可以用at访问list容器的元素
	//原因是list本质是链表,不是用连续线性空间存储数据,迭代器也不支持随机访问的

	cout << "L1:";
	printList(L); cout << string(s, '-') << endl;

	cout << "第一个元素:" << L.front() << endl;
	cout << "最后一个元素:" << L.back() << endl;
	
	//验证迭代器不支持随机访问
	list<int>::iterator it = L.begin();
	it++;// ++it it-- --it 支持双向递增
	cout << "支持双向递增 it++:" << * it << endl;
	cout << string(s, '-') << endl;
	it--;//it-- --it 支持双向递减
	//it = it + 1;//不支持随机访问
	cout << "支持双向递减 it--:" << *it << endl;
	cout << string(s, '-') << endl;
}

在这里插入图片描述

总结:

  • list容器中不可以通过[]或者at方式访问数据
  • 返回第一个元素 — front
  • 返回最后一个元素 — back

2 list 反转和排序

功能描述: 将容器中的元素反转,以及将容器中的数据进行排序

函数原型:

  • reverse(); //反转链表
  • sort(); //链表排序

代码示例:

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


void test1()
{
	int s = 45;
	list<int> L1;
	L1.push_back(25);
	L1.push_back(26);
	L1.push_back(27);
	L1.push_back(28);
	L1.push_back(29);
	L1.push_back(30);

	cout << "反转前\t" << "L1:";
	printList(L1); cout << string(s, '-') << endl;

	L1.reverse();//这是list的成员函数 不是全局函数  注意和vector容器的reserve(预留空间)区别
	cout << "反转后\t" << "L1:";
	printList(L1); cout << string(s, '-') << endl;
}

bool myCompare(int v1, int v2)
{
	//降序 第一个数>第二个数
	return v1 > v2;
}

//排序
void test2()
{
	int s = 45;
	list<int> L2;
	L2.push_back(90);
	L2.push_back(25);
	L2.push_back(55);
	L2.push_back(18);
	L2.push_back(17);
	L2.push_back(95);

	cout << "排序前\t" << "  L2:";
	printList(L2); cout << string(s, '-') << endl;

	L2.sort();//默认升序规则 升序 从小到大
	cout << "升序排序  " << "L2:";
	printList(L2); cout << string(s, '-') << endl;

	//提供一个函数或者仿函数改变排序的规则
	L2.sort(myCompare);
	cout << "降序排序  " << "L2:";
	printList(L2); cout << string(s, '-') << endl;
}

在这里插入图片描述

注意点:

  1. 所有不支持随机访问的迭代器的容器是不可以用标准算法的。
  2. algorithm的算法适用于支持随机访问的迭代器的容器,例如string、vector、deque
  • 例如,sort(L2.begin(), L2.end());,这种是algorithm标准算法类提供,属于全局函数。支持随机访问的迭代器的容器,如string、vector、deque可以使用;不支持随机访问的迭代器的容器,如list不能使用。
  1. 但是,不支持随机访问的迭代器的容器,其内部提供一些对应全局函数的算法。比如sort算法和反转算法,L1.reverse();L2.sort();,这都是容器内部提供的一些成员函数。
  2. list容器内部提供的sort()算法的默认规则是升序,从小到大。如果想要降序,则提供一个外部函数或者反函数实现降序排序。
  3. 在list容器内部,根据容器元素个数来选择算法排序,数据量大和数据量小选择的排序算法不一样
  4. 如果要实现降序排序,
  • 首先,myCompare()的返回值是bool类型,判断两个容器的容量谁大谁小
  • 如果操纵的容器元素是int类型,形参传入也是int类型
  • 然后,降序的话,就让第一个形参>第二个形参
  • 最后,myCompare()函数传给list的成员函数sort,实现降序排序。

总结:

  • 反转 — reverse(成员函数)
  • 排序 — sort (成员函数),注意区别与支持随机访问迭代器的容器(string、vector、deque)的排序算法sort()

3 排序案例

案例描述: 将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高、体重

排序规则: 按照年龄进行升序,如果年龄相同按照身高进行降序;进一步,身高相同,按照体重升序排序

代码示例:

class Person
{
public:
	Person(string name, int age, int height, int weight)
	{
		this->m_name = name;
		this->m_age = age;
		this->m_height = height;
		this->m_weight = weight;
	}
	string m_name;
	int m_age;
	int m_height;
	int m_weight;
};

void printListPerson(const list<Person>& L)
{
	for (list<Person>::const_iterator it = L.begin(); it != L.end(); ++it)
	{
		cout << "姓名:" << (*it).m_name << "\t年龄:" << (*it).m_age 
			<< "\t身高:" << (*it).m_height << "\t体重:" << (*it).m_weight<< endl;
	}
}

//自定义的数据类型,list排序,指定排序规则
bool mycompare(Person& p1, Person& p2)
{
	if (p1.m_age == p2.m_age)//年龄相同
	{
		return p1.m_height > p2.m_height;//按照身高降序排序
	}
	else if(p1.m_height == p2.m_height)//身高相同
	{
		return p1.m_weight < p2.m_weight;//体重升序排序
	}
	else
	{
		return p1.m_age < p2.m_age;
	}
}

void test()
{
	int s = 60;
	list<Person> L;

	//1、创建人物 放入容器
	/*
	//Person p1("张飞", 24, 178);
	//Person p2("刘备", 39, 170);
	//Person p3("西施", 25, 153);
	//Person p4("貂蝉", 30, 162);
	//Person p5("关羽", 23, 182);
	*/
	string nameseed[] = { "张飞", "孙权", "西施", "貂蝉", "王昭君", "关羽" };
	int ageseed[] = { 28, 28, 25, 24, 26, 28 };
	int heightseed[] = { 178, 170, 153, 153, 153, 200 };
	int weightseed[] = { 140, 135, 109, 95, 100, 165 };
	for (int i = 0; i < 6; i++)
	{
		Person p(nameseed[i], ageseed[i], heightseed[i], weightseed[i]);
		L.push_back(p);
	}
	//测试
	printListPerson(L);
	cout << string(s, '-') << endl;
	
	//对于自定义的数据类型,需要传一个自定义函数或是仿函数来指定排序规则
	//年龄升序  身高降序 体重升序 
	cout << "\n排序后" << endl;
	L.sort(mycompare);
	printListPerson(L);
}

在这里插入图片描述
重点在于,mycompare()排序规则函数的写法,让list提供的成员函数sort变成高级排序。

总结:

  • 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
  • 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值