《C和C++程序员面试秘笈》第11章 STL(标准模板库)

摘要

STL的基本概念就是把数据和操作分离
STL含有容器、算法、迭代器等组件
    容器:管理各种类型的数据
    算法:完成操作
    迭代器:在 容器和算法之间充当粘合剂

容器的分类
	序列式容器:vector、string、deque、list
	关联式容器:set、multiset、map、multimap
	适配容器:stack、queue、proprity_queue

1. 什么是STL

容器(containers):涵盖了许多数据结构
	链表、vector(数组)queue(队列)stack()....string也可以看做一个容器,适用于容器的方法同样适用于string
算法(algorithms):包含了大约70个常用算法
	用于操作各种容器,同时也可以操作内建数组
迭代器(iterators):使得容器和算法能够完美的结合
	它有点像指针,算法通过迭代器来 定位和操作容器中的元素

2. 具体说明STL如何实现vector

原型:	
	template<class _Ty,class _A = allocator<_Ty> >
	class vector
	{
		...
	}
vector:动态数组
	1. 内存不够用时,会自动分配内存,一般是扩展为两倍(重新分配内存、拷贝、插入新元素、释放原内存)
	2. 内部使用allocator类进行内存管理(分配、释放、自动回收等)

3. vector容器中iterator的使用

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <algorithm>
#include <vector>
using namespace std;

#if 1
int main()
{
	vector<int> array;
	array.push_back(1);
	array.push_back(2);
	array.push_back(3);

	//size_type是size_t类型,其实就是unsigned int 
	//unsigned int 类型的变量,当减为0时,再减1,这个变量就会变成一个很大的数字
	//此时作为数组下标,就导致越界访问了
	//所以==0时,不能继续减1,此时应该作为终止循环的条件
	vector<int>::size_type i = array.size();
	for (; i > 0; --i)
	{
		cout << array[i - 1] << endl;
	}

	system("pause");
	return EXIT_SUCCESS;
}
#endif

4. vector容器的使用

题目:
	删除vector数组中所有的2
	
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <vector>
using namespace std;

#if 1
int main()
{
	typedef vector<int> IntArray;
	IntArray array;
	array.push_back(1);
	array.push_back(2);
	array.push_back(2);
	array.push_back(3);

	for (IntArray::iterator it = array.begin(); it != array.end(); ++it)//非内置类型最好使用前置++、--
	{
		if (2 == *it)
		{
			//序列式容器,执行删除操作会导致:1、后面的元素集体前移 2、后面所有元素的iterator失效
			//但是erase会返回下一个有效的iterator,可以用来解决iterator失效的问题
			it = array.erase(it);//重新接收iterator
			//元素被删除之后,内容会前移,若是此时直接执行it++,则会漏检这一项
			//所以先对it--,再对*it进行检测,相当于继续检测刚刚的位置
			--it;//
		}
	}
	for (IntArray::iterator it = array.begin(); it != array.end(); it++)
	{
		cout << *it << endl;
	}
	system("pause");
	return 0;
}
#endif

注意:
	对于序列式容器(如vector,deque),序列式容器就是数组式容器,删除当前的iterator会使后面所有元素的iterator都失效。
		这是因为序列式容器使用了连续分配的内存(分配一个数组作为内存),删除一个元素导致后面所有的元素会向前移动一个位置。
		(删除了一个元素,该元素后面的所有元素都要挪位置,所以,iter++,已经指向的是未知内存)。
		所以不能使用erase(iter++)的方式
解决方法:
	erase方法可以返回下一个有效的iterator



迭代器失效分三种情况考虑,也是三种数据结构考虑,分别为数组型,链表型,树型数据结构。
	1、序列式/数组型数据结构:该数据结构的元素是分配在连续的内存中,
		insert和erase操作,都会使得删除点和插入点之后的元素挪位置,
		所以,插入点和删除掉之后的迭代器全部失效,也就是说insert(iter)(erase(iter)),然后再iter++,是没有意义的。
		解决方法:
			erase(iter)的返回值是下一个有效迭代器的值
			-->iter =cont.erase(iter);
	2、链表型数据结构:对于list型的数据结构,使用了不连续分配的内存,
		删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器
		解决办法两种:
			1. iter=erase(iter)  erase(iter)会返回下一个有效迭代器的值,
			2. 或者erase(iter++).
	3、树形数据结构:使用红黑树来存储数据,
		插入不会使得任何迭代器失效;
		删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器
			erase迭代器只是被删元素的迭代器失效,但是返回值为void,
		解决方法:
			所以要采用erase(iter++)的方式删除迭代器。
	注意:经过erase(iter)之后的迭代器完全失效,该迭代器iter不能参与任何运算,包括iter++,*ite
关于iterator失效的几种情况:博客链接:https://blog.csdn.net/lujiandong1/article/details/49872763 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值