STL之list

4 篇文章 0 订阅

list同样是序列式容器,可排序但是未排序。
list和vector相比较,list的优点是每次插入或删除一个元素,就会分配或释放一个元素都空间。因此,list对空间的运用有绝对的精准,一点儿也不浪费。而且,list对于任何位置的元素的插入或移除,时间复杂度永远是常数级。

下面我们从节点、迭代器、list结构、list 的constructor, push_back, insert、list元素的操作这五点进行分析。

1.节点
首先看一下list的节点(node)的定义

template <class T>
struct __list_node {
	typedef void* void_pointer;
	void_pointer prev; // 类型为 void*。其实可设为 __list_node<T>*
	void_pointer next;
	T data;
};

可以看到每个node有自己的数据,并且有前指针和后指针。
显然这个是一种双向链表。
在这里插入图片描述
值得注意的是,list的节点不保证在空间上是连续存储的。

2.迭代器
list有一个重要的特性,插入动作(insert)和接合动作(splice)都不会造成原有的list的迭代器失效。这在vector是不成立的,因为vector的插入动作造成记忆体重新配置,导致原有的迭代器全部失效。甚至list的删除动作(erase),也只有【指向被删除元素】的那个迭代器失效,其他迭代器不受任何影响。
在这里插入图片描述
3.list的结构
正如前面提到的那样,list是个双向链表,但是不仅如此,它还是个环状链表,因此只需要一个指针就可以完成整个list的遍历。
在这里插入图片描述
4.list 的constructor, push_back, insert
话不多说,先看一下list的这三种基本操作

    int i;
	list<int> ilist;
	cout << "size=" << ilist.size() << endl; // size=0
	ilist.push_back(0);
	ilist.push_back(1);
	ilist.push_back(2);
	ilist.push_back(3);
	ilist.push_back(4);
	cout << "size=" << ilist.size() << endl; // size=5
	
	list<int>::iterator ite;
	for (ite = ilist.begin(); ite != ilist.end(); ++ite)
		cout << *ite << ' '; // 0 1 2 3 4
	cout << endl;
	
	ite = find(ilist.begin(), ilist.end(), 3);
	if (ite !=ilist.end())
		ilist.insert(ite, 99);
	cout << "size=" << ilist.size() << endl; // size=6
	cout << *ite << endl; // 3
	for (ite = ilist.begin(); ite != ilist.end(); ++ite)
		cout << *ite << ' '; // 0 1 2 99 3 4
	cout << endl;
	
	ite = find(ilist.begin(), ilist.end(), 1);
	if (ite != ilist.end())
		cout << *(ilist.erase(ite)) << endl; // 2
	for (ite = ilist.begin(); ite != ilist.end(); ++ite)
		cout << *ite << ' '; // 0 2 99 3 4
	cout << endl;

输出:
在这里插入图片描述
list有许多constructors,其中的一个是default constructor,允许我们不指定任何参数做出一个空的list

当我们以 push_back() 將新元素安插于 list 尾端,此函数內部呼叫 insert() :

void push_back(const T& x) { insert(end(), x); }

而insert有多种重载类型,其中一下如下

// 函式目的:在迭代器 position 所指位置安插一个节点,內容为 x。
iterator insert(iterator position, const T& x)

由于 list 不像 vector 那样有可能在空间不足时做重新配置、资料搬移的动作,所以插入前的所有迭代器在插入动作之后都仍然有效。
在这里插入图片描述
5.list 的元素操作:push_front, push_back, erase, pop_front, pop_back,clear, remove, unique, splice, merge, reverse, sort
功能描述

// 安插一个节点,做为头节点
void push_front(const T& x) { insert(begin(), x); }
// 安插一个节点,做为尾节点(上一小节才介紹过)
void push_back(const T& x) { insert(end(), x); }
// 移除迭代器 position 所指节点
iterator erase(iterator position)
// 移除头结点
void pop_front() { erase(begin()); }
// 移除尾节点
void pop_back()
// 清除所有节点(整個链表)
template <class T, class Alloc>
void list<T, Alloc>::clear()
// 將数值为value 的所有元素移除
template <class T, class Alloc>
void list<T, Alloc>::remove(const T& value)
// 移除数值相同的连续元素。注意,只有「连续而相同的元素」,才会被移除剩一个。
template <class T, class Alloc>
void list<T, Alloc>::unique()

下图展示了移除值为1的节点
在这里插入图片描述
下面是splice、reverse、sort操作,输出即为注释。

    int iv[5] = { 5,6,7,8,9 };
	list<int> ilist2(iv, iv + 5);
	// 目前,ilist 的內容為 0 2 99 3 4
	ite = find(ilist.begin(), ilist.end(), 99);
	ilist.splice(ite, ilist2);  // 0 2 5 6 7 8 9 99 3 4
	ilist.reverse(); // 4 3 99 9 8 7 6 5 2 0
	ilist.sort(); // 0 2 3 4 5 6 7 8 9 99

在这里插入图片描述

// merge() 將 x 合并到 *this 身上。两个 lists 的內容都必须先经过递增排序。
template <class T, class Alloc>
void list<T, Alloc>::merge(list<T, Alloc>& x)

具体操作

	int d1[5] = { 1,3,5,7,9 };
	int d2[5] = { 2,4,6,8,10 };
	list<int> list1(d1,d1+5);//前闭后开区间
	list<int> list2(d2,d2+5);
	list1.merge(list2);
	list<int>::iterator it;
	for (it = list1.begin(); it != list1.end(); ++it)
		cout << *it << " ";
	cout << endl;

输出:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值