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;
}
注意点:
- 所有不支持随机访问的迭代器的容器是不可以用标准算法的。
- algorithm的算法适用于支持随机访问的迭代器的容器,例如string、vector、deque
- 例如,
sort(L2.begin(), L2.end());
,这种是algorithm标准算法类提供,属于全局函数。支持随机访问的迭代器的容器,如string、vector、deque可以使用;不支持随机访问的迭代器的容器,如list不能使用。
- 但是,不支持随机访问的迭代器的容器,其内部会提供一些对应全局函数的算法。比如sort算法和反转算法,
L1.reverse();
、L2.sort();
,这都是容器内部提供的一些成员函数。 - list容器内部提供的sort()算法的默认规则是升序,从小到大。如果想要降序,则提供一个外部函数或者反函数实现降序排序。
- 在list容器内部,根据容器元素个数来选择算法排序,数据量大和数据量小选择的排序算法不一样
- 如果要实现降序排序,
- 首先,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变成高级排序。
总结:
- 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
- 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂