【C++第三阶段】list容器&排序

以下内容仅为当前认识,可能有不足之处,欢迎讨论!



image-20240411211821277

list容器在STL中是双向循环链表。

如图所示,每一个节点三个域,前向指针域,后向指针域,数据域。前向指针域指向前一个结点的地址,后向指针域指向后一个结点的地址,数据与存放该结点数据。第一个结点的前向指针指向最后一个结点的地址;最后一个结点的后向指针指向第一个结点的地址。

但是值得注意的是,插入删除操作不会造成list迭代器的失效,而迭代器在vector中是一次性的。

list优点:

采用动态存储分配,不会造成内存浪费和溢出。

链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素。

list缺点:

链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大。

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

总结:STL中list和vector是两个最常使用的容器,各有优缺点。

构造函数

目的函数
默认构造形式list<T> lst;
将[beg,end)区间中的元素拷贝给本身list(beg,end);
构造函数将n个elem拷贝给本身list(n,elem);
拷贝构造函数list(const list &lst);

示例代码:

void test0419a() {
	list<int> lst;
	lst.push_back(10);
	lst.push_back(20);
	lst.push_back(30);
	lst.push_back(40);
	print(lst);

	cout << "区间元素拷贝给本身" << endl;
	list<int> lst2(++lst.begin(), lst.end());
	print(lst2);

	cout << "构造函数将n个elem拷贝给本身" << endl;
	list<int> lst3(3, 6);
	print(lst3);

	cout << "拷贝构造函数" << endl;
	list<int> lst4 = lst2;
	print(lst4);
}

运行结果:

image-20240428205708289

赋值和交换

赋值和交换,说的是list容器中,给list容器进行赋值,以及交换list容器。

目的函数原型
将区间内的数据赋值给本身assign(begin,end);
将n个elem拷贝赋值给本身assign(n,elem);
重载等号操作符list& operator=(const list &lst);
将lst与本身的元素互换swap(lst);

示例代码:

void test0428a() {
	list<int> lst;
	for (int i = 10; i < 14; i++) {
		lst.push_back(i*2/3+1);
		lst.push_front(i * 3 / 2-1);
	}
	cout << "lst为↓" << endl;
	print(lst);

	list<int> lst2;
	lst2.assign(lst.begin(), lst.end());
	cout << "lst2为↓" << endl;
	print(lst2);

	list<int> lst3;
	lst3 = lst;
	cout << "lst3为↓" << endl;
	print(lst3);

	list<int> lst4;
	cout << "lst4为↓" << endl;
	lst4.assign(10, 100);
	print(lst4);

	swap(lst3, lst4);
	cout << "lst3为↓" << endl;
	print(lst3);
	cout << "lst4为↓" << endl;
	print(lst4);

}

运行结果:

image-20240428211919091

大小操作

目的:对容器的大小进行操作

目的函数
返回容器中元素个数size()
判断容器是否为空empty()
重新制定容器长度,后长度若长于原长度,则以默认值填充,后长度若短于原长度,则截断。resize(num)
以指定值填充。resize(num,elem)

示例代码:

void test0429a() {
	list<int> lst;
	for (int i = 1; i < 4; i++) {
		lst.push_back(i * 2 - 3);
		lst.push_front(i * 3 - 2);
	}
	cout << "lst当前为:";
	print(lst);
	cout << "lst的元素个数:" << lst.size() << "." << endl;
	cout << "lst是空list容器吗?" << endl;
	if (lst.empty()) {
		cout << "lst是空容器。" << endl;
	}
	else {
		cout << "lst不是空容器。" << endl;
	}
	cout << "重新lst裁剪大小为4个" << endl;
	lst.resize(4);
	print(lst);
	cout << "扩充lst为7个,以7填充。" << endl;
	lst.resize(7, 7);
	print(lst);
}

运行结果:

image-20240429094748862

插入和删除

目的:对list容器进行数据的插入和删除。

目的函数
容器尾部添加一个元素push_back(elem)
删除容器最后一个元素pop_back()
容器开头添加一个元素push_front(elem)
删除容器最后一个元素pop_front()
在pos位置插入elem元素的拷贝,返回新数据的位置insert(pos,elem)
在pos位置插入n个elem数据, 不需要返回值insert(pos,n,elem)
在pos位置插入[begin,end)区间的数据,没有返回值insert(pos,begin,end)
删除容器中所有数据clear()
删除[begin,end)区间的数据,返回下一个数据的位置。erase(begin,end)
删除pos位置的数据,返回下一个数据的位置erase(pos)
删除容器中所有值为elem的元素remove(elem)

示例代码:

void test0429b() {
	list<int> lst;
	list<int> tsl;
	for (int i = 0; i < 4; i++) {
		lst.push_back(i * 2 - 5);
		lst.push_front(i * 5 - 2);
		tsl.push_back(i);
	}
	cout << "lst当前为↓" << endl;
	print(lst);

	cout << "删除lst头部第一个元素后,lst↓" << endl;
	lst.pop_front();
	print(lst);
	cout << "删除lst尾部最后一个元素后,lst↓" << endl;
	lst.pop_back();
	print(lst);

	list<int> ::iterator begin = lst.begin();

	cout << "在第2个位置插入1个3" << endl;
	lst.insert(++begin, 3);
	print(lst);
	
	cout << "在第3个位置插入4个2" << endl;
	lst.insert(++begin, 4, 2);
	print(lst);

	cout << "lst当前为↓" << endl;
	print(lst);
	cout << "tsl当前为↓" << endl;
	print(tsl);

	cout << "lst尾部插入tsl后,lst为↓" << endl;
	lst.insert(lst.end(), tsl.begin(), tsl.end());
	print(lst);

	cout << "lst删除第一个元素的位置,返回下一个数据的位置为" << endl;
	lst.erase(lst.begin());
	print(lst);

	cout << "此时begin的位置对应的元素是" << *begin << endl;

	cout << "lst删除第begin+1个到最后一个元素的数据后,为↓" << endl;
	lst.erase(++begin, lst.end());
	print(lst);
	
}

运行结果:

image-20240429102550302

数据存取

目的:对list容器中数据进行存取

目的函数
返回第一个元素值front()
返回最后一个元素值back()

示例代码:

void test0429c() {
	list<int> lst;
	for (int i = -2; i < 3; i++) {
		lst.push_back(i * 2 - 2);
	}
	print(lst);
	cout << "第一个元素值为:" << lst.front() << endl;
	cout << "最后一个元素值为:" << lst.back() << endl;

}

运行结果:

image-20240429103149556

list不可以用[]访问容器中的元素,也不可以用at()方式访问容器中的元素。

因为list是链表,不是用连续线性空间存储数据,迭代器也是不支持随机访问的。

反转和排序

目的:①反转list容器内元素;②对list容器进行排序。

反转可以直接用容器内方法,排序

所有不支持随机访问迭代器的容器,不可以用标准算法。

所以,要想对这些容器进行排序,可以使用内部提供的对应算法。

排序默认是升序,如果是降序,则需要写一个对应函数。

示例代码:

void test0429d() {
	list<int> lst;
	for (int i = -2; i < 3; i++) {
		lst.push_back(i * 2 - 2);
		lst.push_front(i * i - 2);
	}
	cout << "now lst -->"<<endl;
	print(lst);
	cout << endl;

	cout << "after reverse,the lst ==" << endl;
	lst.reverse();
	print(lst);
	cout << endl;

	cout << "after sort ,lst == " << endl;
	lst.sort();
	print(lst);
	cout << endl;

	cout << "now sort by function compare , lst == " << endl;
	lst.sort(compare<int>);
	print(lst);
	cout << endl;
}

运行结果:

image-20240429105248422

排序案例

案例描述:将person自定义数据类型排序,属性有姓名,年龄,身高。

规则:按照年龄进行升序(默认),如果年龄相同,则按照身高进行降序。

疑问:怎么通过某一个属性进行排序?

看视频解决:通过自定义的排序函数。

示例代码:

#include<iostream>

#include<string>

using namespace std;

#include<list>

template<typename T>
void print(list<T>& lst) {
	for (typename list<T>::iterator lst_front = lst.begin(); lst_front != lst.end(); ++lst_front) {
		cout << *lst_front;
		//cout << "  ";
	}
	cout << endl;
}

class Person {
public:
	Person() {};
	Person(string name, int age, double height) :person_name(name), person_age(age), person_height(height) {};
public:
	string person_name;
	int person_age;
	double person_height;
};

ostream& operator<<(ostream& out, Person& person) {
	cout << person.person_name << "年龄为:" << person.person_age << ",\t身高为:" << person.person_height << "." << endl;
	//在实现operator<<时,最好不要直接使用cout,而应该使用传递给函数的ostream对象out,这可以提高代码的可复用性。——GPT4
	return out;
}


//template <typename Person>
bool person_compare(const Person& per, const Person& son) {
	if (per.person_age == son.person_age) {
		return per.person_height > son.person_height;
	}
	return son.person_age > per.person_age;
}

void test0429e() {
	Person person[5];

	Person One("大道", 20, 1.85);
	person[0] = One;

	Person Two("两极", 19, 1.83);
	person[1] = Two;

	Person Three("三眼", 22, 1.84);
	person[2] = Three;

	Person Four("四象", 22, 1.86);
	person[3] = Four;

	Person Five("五行", 24, 1.88);
	person[4] = Five;

	list<Person> lst_ps;
	for (int i = 0; i < (sizeof(person) / sizeof(person[0])); i++) {
		lst_ps.push_back(person[i]);
	}
	cout << "Person 排序前" << endl;
	print(lst_ps);

	cout << "Person 排序后" << endl;
	lst_ps.sort(person_compare);
	print(lst_ps);

}

int main() {

	test0429e();

	system("pause");
	return 0;
}

运行结果:

image-20240429115426985


以上是我的学习笔记,希望对你有所帮助!
如有不当之处欢迎指出!谢谢!

学吧,学无止境,太深了

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在使用vector容器进行排序时,可以使用sort函数来实现。sort函数默认将元素从小到大进行排序。可以通过使用greater<int>()作为第三个参数来改变排序顺序,将元素从大到小排序。以下是几种实现方法: 方法一:使用sort函数和greater<int>()作为参数 ``` #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int a[] = {8, 6, 2, 9, 3, 5, 4, 1, 7, 10}; vector<int> arr(a, a + 5); sort(arr.begin(), arr.end(), greater<int>()); for (int i = 0; i < arr.size(); i++) { cout << arr[i << " "; } return 0; } ``` 方法二:使用自定义函数cmp_max作为参数 ``` #include <iostream> #include <vector> #include <algorithm> using namespace std; bool cmp_max(int x, int y){ return x > y; } int main() { int a[] = {8, 6, 2, 9, 3, 5, 4, 1, 7, 10}; vector<int> arr(a, a + 5); sort(arr.begin(), arr.end(), cmp_max); for (int i = 0; i < arr.size(); i++) { cout << arr[i << " "; } return 0; } ``` 方法三:先使用sort函数排序,再使用reverse函数倒置元素顺序 ``` #include <iostream> #include <vector> #include <algorithm> using namespace std; int main() { int a[] = {8, 6, 2, 9, 3, 5, 4, 1, 7, 10}; vector<int> arr(a, a + 5); sort(arr.begin(), arr.end()); reverse(arr.begin(), arr.end()); for (int i = 0; i < arr.size(); i++) { cout << arr[i << " "; } return 0; } ``` 以上是几种在vector容器中进行排序的方法,具体选择哪种方法取决于你的需求和喜好。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++ vector容器排序 (从小到大,从大到小)](https://blog.csdn.net/pure_dreams/article/details/113992178)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

HelpFireCode

随缘惜缘不攀缘。

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

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

打赏作者

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

抵扣说明:

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

余额充值