C++ | list用法指南

目录

前言

一、链表的分类

二、构造与析构

三、迭代器

1、迭代器的种类

2、list迭代器的使用

 四、容量相关接口

五、修改相关接口

六、其他成员接口


前言

        经过前几章节的学习,我们对STL的vector和string容器接口的使用已经非常深刻了,这里我们继续学习STL中的list------也就是链表;

一、链表的分类

        实际上,前面的文章中,我们用C语言实现了一个单链表,在STL中,实际上也分单链表和双向循环带头链表,而我们大部分使用的都是双向带头循环链表;单链表的讲解点击这里(C语言版)

 本文主要讲解双向带头循环链表的使用,也就是list;

二、构造与析构

        想学会使用一种容器,我们首先得知道其构造如何调用;(析构出作用域自动调用)

构造如下: 

 赋值重载:

void test_list1()
{
	// 默认构造
	list<int> lt1;
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
	// n个data构造
	list<int> lt2(8, 6);
	for (auto& e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;
	// 区间构造
	int array1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
	list<int> lt3(array1, array1 + 5);
	for (auto& e : lt3)
	{
		cout << e << " ";
	}
	cout << endl;
	// 拷贝构造
	list<int> lt4(lt3);
	for (auto& e : lt4)
	{
		cout << e << " ";
	}
	cout << endl;
	// 赋值重载
	list<int> lt5;
	lt5 = lt4;
	for (auto& e : lt5)
	{
		cout << e << " ";
	}
	cout << endl;
}

        实际上,以上构造接口的调用与前面的string与vector几乎差不多;因此,熟练使用其中一个,其他上手也不难;

三、迭代器

        在list中,想要遍历一个链表中所有数据,迭代器就是最好的选择,迭代器也是所有STL容器中最通用的遍历方法,因为链表的数据不是储存在一段连续的空间中,因此,我们想通过方括号的方式访问成员就不太现实了,以及后面我们要学的树形结构的容器,都是使用迭代器的方式访问数据,因此方括号的遍历方式并不是常态,而恰恰迭代器的访问遍历才是我们常态;

1、迭代器的种类

        在前面的学习中,我们并没有提出迭代器种类这一概念,但实际上,迭代器分为三类;分别是;

  • 随机迭代器
  • 双向迭代器
  • 单项迭代器

        随机迭代器就像我们vector的迭代器,可以指定访问某个数据,可通过加减O(1)的时间内访问某个数据;

        双向迭代器主要就是我们今天学的 list 了,其虽然不是一段连续的内存空间,但我们可以对其进行++或--来依次遍历容器中的每一个数据;

        单向迭代器主要是我们的容器 forward_list ,也就是我们的单链表,由于其迭代器只能往一个方向遍历,不能双向访问;

2、list迭代器的使用

 list的迭代器也是有如下几种类型的接口,分别为普通,常量,反向三种;

void PrintList(const list<int>& lt)
{
	// 常量迭代器
	list<int>::const_iterator cit = lt.cbegin();
	while (cit != lt.cend())
	{
		cout << *cit << " ";
		cit++;
	}
	cout << endl;
}

void test_list2()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	
	// 普通迭代器遍历
	list<int>::iterator it = lt1.begin();
	// 注意此处不能写成 <= 了,因为储存的空间不连续
	while (it != lt1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	// 范围for
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
	// 反向迭代器
	list<int>::reverse_iterator rit = lt1.rbegin();
	while (rit != lt1.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;

	PrintList(lt1);
}

 四、容量相关接口

        与前面几个容器相比,list的容量接口就少了很多;

void test_list3()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	lt1.push_back(5);
	// 当前元素个数
	cout << lt1.size() << endl;
	// 是否为空
	cout << lt1.empty() << endl;
	// 最大可容纳元素个数
	cout << lt1.max_size() << endl;
}

五、修改相关接口

        这部分接口看着挺多,但实际上,我们大部分都认识,比如assign是给list新的内容,代替原来的老内容,push_back、push_front、pop_back、pop_front分别是头插、尾插、尾删、头删;insert是指定位置插入数据,erase是指定位置删除数据,swap是交换两个链表的头指针,resize是设置某个链表的值,规则与vector的resize相同,clear则是清空链表;其余emplace系列可暂时不管;下面将演示其中几种;

void test_list4()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	lt1.push_back(5);

	// 某个位置插入一个值
	lt1.insert(lt1.begin(), 100); // 100 1 2 3 4 5
	// 某个位置插入n个data
	list<int>::iterator pos = find(lt1.begin(), lt1.end(), 3);
	lt1.insert(pos, 3, 30); // 100 1 2 30 30 30 3 4 5
	// 某个位置插入某段区间的值
	vector<int> v1(lt1.begin(), lt1.end()); 
	pos = find(lt1.begin(), lt1.end(), 5);
	lt1.insert(pos, v1.begin() + 2, v1.begin() + 4); // 100 1 2 30 30 30 3 4 2 30 5
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;

	// 删除某个位置的值
	lt1.erase(lt1.begin()); // 1 2 30 30 30 3 4 2 30 5
	// 删除某个区间的值
	pos = find(lt1.begin(), lt1.end(), 3);
	lt1.erase(lt1.begin(), pos); //3 4 2 30 5
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
}

六、其他成员接口

        在list中还有一些功能性的接口,但是用的并不是很多,也比较特殊,这里可以了解了解;(无需完全记住,用的时候查看文档即可) 文档链接

void test_list5()
{
	list<int> lt1;
	lt1.push_back(1);
	lt1.push_back(2);
	lt1.push_back(3);
	lt1.push_back(4);
	lt1.push_back(5);
	list<int> lt2;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);

	// splice(把某个链表的数据转移到另一个链表的某个位置中)
	lt1.splice(lt1.begin(), lt2);
	// 此时 lt1: 10 20 30 1 2 3 4 5
	// lt2: empty
	// remove 移除某个链表中所有的val
	lt1.remove(2); //  10 20 30 1 3 4 5
}

        unique则负责去重,merge负责排序;因为算法库中的sort只能用随机迭代器,故list也实现了一个排序(merge),reverse则是反转链表;如果这些用法如果用的时候再去文档中查询即可;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值