(C++) list认识与应用 迭代器 默认成员函数 容量相关函数 内部数据访问与修改 去重 排序 转移

# 0 list

list是一个双向带头循环链表。
要使用list,需包含头文件:

#include<list>

list底层的空间并不连续,所以没有了[ ]的重载,不支持使用下标访问。

以及没有扩容这种概念,因为链表的空间以节点为单位,按需申请释放。

# 1 迭代器

list的迭代器不再是原生指针,因为底层的空间并不连续。
从实现的角度上说,list的迭代器与vector大不相同。

但是从使用的角度上来看,迭代器的意义便是给所有容器提供统一的访问与遍历方式。
所以list和其他容器的迭代器,在使用上完全相同。
在这里插入图片描述
依旧是这八个函数,依旧是原本的使用方法。
不再赘述了。

# 2 默认成员函数

对大部分容器来说,析构函数会自动调用,两个取地址重载也不需要自己调用。
所以需要掌握使用的只有构造,拷贝构造和赋值重载。

其中拷贝构造和赋值重载的使用极其简单。
也就构造有多个重载,需要列出来看看。

在这里插入图片描述
三种构造,分别是:
1.无参
2.创建有n个节点的链表,每个节点的值为val。
val有缺省值。
3.用一段迭代器区间构造

第四个是拷贝构造,用另一个list来初始化。

void Test1()
{
	list<int> l1;
	for (auto e : l1)
	{
		cout << e << " ";
	}
	cout << endl;

	list<int> l2(10, 5);
	for (auto e : l2)
	{
		cout << e << " ";
	}
	cout << endl;

	list<int> l3(l2.begin(), l2.end());
	for (auto e : l3)
	{
		cout << e << " ";
	}
	cout << endl;

	list<int> l4 = l3;
	for (auto e : l4)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

# 3 容量相关函数

由于没有容量的概念。list并没有reserve函数。
但是依然有resize函数。

# 3.1 empty

判空,空则返回1,非空则返回0。
没什么好说的。

void Test2()
{
	list<int> l1;
	for (auto e : l1)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << l1.empty() << endl;

	list<int> l2(5, 1);
	for (auto e : l2)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << l2.empty() << endl;
}

在这里插入图片描述

# 3.2 size

返回list中的节点个数。
同时也是数据个数。

# 3.3 resize

在这里插入图片描述

重新指定list的节点个数。
有这么三种情况:

1.目标size与原size相同:
那当然是什么都不做。

2.目标size大于原size:
将会不断地尾插新节点,直到总节点数量达到指定size。
这些节点的值就是val,可以缺省,调用数据类型的默认构造。

3.目标size小于原size:
那么数据将会被截断。
保留原链表的前目标size个数据,后续的数据将被删除,相应的空间也会被释放。

void Test3()
{
// 原size是6
	list<int> l(6, 7);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// resize到6,没有变化
	l.resize(6);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// resize到10,使用缺省值,对于整型来说就是0
	l.resize(10);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// reszie到1,后续数据都被删除
	l.resize(1);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// resize到5,用10来填充
	l.resize(5, 10);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

# 4 内部数据访问与修改

list有push_front,pop_front,push_back,pop_back这些函数,即头插头删,尾插尾删。

这些函数操作,本质上都是通过insert和erase,
也就是将目标迭代器位置指定成头,或者尾来实现的。

# 4.1 任意位置插入 insert

在这里插入图片描述
三种重载:

1.单个数据的插入。
参数为目标位置的迭代器和插入的值。

2.多个数据的填充。
参数为目标位置的迭代器,要插入填充的节点数量n,和填充的值val。

3.多个数据的插入。
参数为目标位置的迭代器,以及一段迭代器区间。

void Test4()
{
	list<int> l(3, 3);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// 插入单个数据
	l.insert(l.end(), 4);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// 插入2个5
	l.insert(l.end(), 2, 5);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// 将ll尾插到l
	list<int> ll(5, 1);
	l.insert(l.end(), ll.begin(), ll.end());
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

# 4.2 任意位置删除 erase

在这里插入图片描述
两种重载:

1.单个数据删除。
删除目标迭代器位置的节点。

2.多个数据删除。
删除一段迭代器区间内的所有节点。

void Test5()
{
	list<int> l;
	l.insert(l.end(), 1);
	l.insert(l.end(), 2);
	l.insert(l.end(), 3);
	l.insert(l.end(), 4);
	l.insert(l.end(), 5);
	l.insert(l.end(), 6);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// 删除单个数据
	l.erase(l.begin());
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

// 删除一段迭代器区间
	l.erase(l.begin(), l.end());
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

# 4.3 交换 swap

交换两个list。

# 4.4 清空 clear

清空list内的所有数据。
并不是删除整个链表,只是删除整个链表中的数据,头节点还保留着。
还支持继续插入新数据。

# 5 其他操作

# 5.1 排序 sort

list内自带的sort本质上是快排,效率并不高。

# 5.2 去重 unique

可以去除链表中连续的重复值。
如果重复值并不连续,unique函数并不能正确的识别他们。
可以搭配前面的sort使用,达到真正的去重。

void Test6()
{
	list<int> l;
	l.insert(l.end(), 1);
	l.insert(l.end(), 2);
	l.insert(l.end(), 3);
	l.insert(l.end(), 4);
	l.insert(l.end(), 5);
	l.insert(l.end(), 2);
	l.insert(l.end(), 2);
	l.insert(l.end(), 2);
	l.insert(l.end(), 6);
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

	l.unique();
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

	l.sort();
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;

	l.unique();
	for (auto e : l)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述

# 5.3 转移 splice

将一个链表的节点,插入到另一个链表中的目标节点后。
两个链表可以是同一个链表,即支持自己对自己的转移操作。

转移操作并不是拷贝,被转移的节点是在两个,或者一个链表中移动。

在这里插入图片描述
三种重载:

1.整个链表的转移。
将链表x的所有节点转移到目标迭代器位置。

2.单个节点的转移。
同样是将链表x转移到目标迭代器位置,
不同的是并非整个链表,转移的仅是链表x的 i 迭代器位置所对应的节点。

3.一段迭代器区间的转移。
将链表x的一段迭代器区间转移到目标迭代器位置。

void Print(list<int>& l1, list<int>& l2, list<int>& l3)
{
	cout << "l1:";
	for (auto e : l1)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "l2:";
	for (auto e : l2)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "l3:";
	for (auto e : l3)
	{
		cout << e << " ";
	}
	cout << endl;
}

void Test7()
{
	list<int> l1;
	list<int> l2(3, 7);
	list<int> l3(2, 8);
	l1.insert(l1.end(), 10);
	l1.insert(l1.end(), 20);
	l1.insert(l1.end(), 30);
	l1.insert(l1.end(), 40);

	Print(l1, l2, l3);

// 转移整个链表
	l1.splice(l1.begin(), l2);
	cout << endl;

	Print(l1, l2, l3);

// 转移单个节点
	l1.splice(l1.begin(), l3, l3.begin());
	cout << endl;

	Print(l1, l2, l3);

// 单个链表内的迭代器区间转移
	l1.splice(l1.end(), l1, ++l1.begin(), --l1.end());
	cout << endl;

	Print(l1, l2, l3);
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值