知识梳理:标准模板库STL

基本概念

  • 容器:可容纳各种数据类型的通用数据结构,是类模板。
  • 迭代器:可用于依次存取容器中的元素,类似于指针
  • 算法:用来操作容器中的元素的函数模板

sort()来对一个vector中的数据进行排序
find()来搜索一个list中的对象

算法本身与它们操作的数据的类型无关,因此它们可以在从简单数组到高度复杂容器的任何数据结构上使用。

容器概述
可以用于存放各种类型的数据(基本类型的变量、对象等)的数据结构,都是类模板,分为三种:

  1. 顺序容器:vector\deque\list
  2. 关联容器:set\multiset\map\multimap
  3. 容器适配器:stack\queue\priority_queue

对象被插入到容器时,被插入的是对象的一个复制品。许多算法如排序、查找要求对容器的元素进行比较,有的容器本身就是排序的,所以,放入容器的对象所属的类,往往还应该重载==和<运算符。

顺序容器

容器并非排序的,元素的插入位置通元素的值无关,有vector\deque\list三种。

vector
加上头文件。动态数组。元素在内存中连续存放。随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳的性能(大部分情况下是常数时间)。

deque
双向队列,头文件是.元素在内存连续存放。随机存取任何元素都能够在常数时间内完成,但次于vector。在两端增删元素具有较佳的性能,大部分是常数时间。

list
头文件。双向链表。元素在内存中不连续存放,在任何位置增删元素都能在常数时间完成。不支持随机存取。

关联容器

  1. 元素是排序的。
  2. 插入任何元素,都按相应的排序规则来确定其位置
  3. 在查早时具有很好的性能
  4. 通常以平衡二叉树的方式实现,插入和检索时间都是O(logN)

set/multiset
头文件。集合。set中不允许相同的元素,multiset中允许出现相同的元素。

map/multimap
头文件。map和set的不同在于map中存放的元素有且仅有两个成员变量,分别为first和second。map根据first值对元素进行从小到大排序,并可快速的根据forst来检索元素。map和multimap区别在于是否允许相同first值的元素。

容器适配器

stack
头文件.栈。是项的有限序列,并满足序列中被删除、检索和修改的项只能是最近插入序列的项。后进先出原则。

queue
队列。插入只可以在尾部进行,删除、检索和修改只允许从头部进行,先进先出。

priority_queue
优先级队列。最高优先级元素总是第一个出列。

顺序容器和关联容器都有的成员函数

begin	返回指向容器中第一个元素的迭代器
end		返回指向容器中最后一个元素后面的位置的迭代器
rbegin	返回指向容器中最后一个元素的迭代器
rend	返回指向容器中第一个元素前面的位置的迭代器
erase	从容器中删除一个或几个元素
clear	从容器中删除所有的元素

顺序容器中常用的成员函数

front	返回容器中第一个元素的引用
back	返回容器中最后一个元素的引用
push_back在容器末尾增加新的元素
pop_back删除容器末尾的元素
erase	删除迭代器指向的元素(可能会使该迭代器失效)或删除一个区间,返回被删除元素后面的那个元素的迭代器

迭代器

用于指向顺序容器和关联容器中的元素。迭代器的用法和指针类似,有const和非const两种。通过迭代器可以读取它指向的元素,通过非const迭代器还能修改其指向的元素。

定义一个容器类的迭代器的方法可以是:
	容器类名::iterator 变量名;
或
	容器类名::const_iterator 变量名;
访问一个迭代器指向的元素:*迭代器变量名

迭代器上可以执行++操作,以使其指向容器的下一个元素。如果迭代器到达了容器中的最后一个元素的后面,此时再使用它就会出错,类似于使用NULL或未初始化的指针一样。

vector<int>::reverse_iterator r;//反向迭代器
for(r=v.rbegin();r!=v.rend();r++)
	cout<<*r<<",";

双向迭代器
若p和p1都是双向迭代器,则可以对p和p1进行以下操作:

++p, p++	使p指向容器中下一个元素	
--p, p--	使p指向容器中上一个元素
*p			取p指向的元素
p=p1;		赋值
p=p1,p!=p1	判断是否相等或不等

随机访问迭代器
若p和p1都是随机访问迭代器,则可对p1和p进行以下操作

双向迭代器的所有操作
p+=i 将p向后移动i个元素
p-=i 将p向前移动i个元素
p+i	 值为:指向p后面的第i个元素的迭代器
p-i  值为:指向p前面的第i个元素的迭代器
p[i] 值为:p后面的第i个元素的引用
p<p1,p<=p1,p>p1,p>=p1:可以比较大小,指的是元素的前后之分

vector/deque都是随机访问的迭代器;list/set/map都是双向的迭代器。stack\queue等不支持迭代器。

算法简介

算法就是一个个函数模板,大多数在中定义。

STL中提供能在各种容器中通用的算法,如查找、排序等。算法通过迭代器来操纵容器中的元素,许多算法可以对容器中的一个局部区间进行操作,因此需要两个参数,一个是起始元素的迭代器,一个是终止元素的后面一个元素的迭代器。

有的算法返回一个迭代器,如find()算法,在容器中查找一个元素,并返回一个指向该元素的迭代器。算法可以处理容器也可以处理普通数组。

大小概念
关联容器内部的元素是从小到大排序的。有些算法要求其操作的区间是从小到大排序的,称为“有序区间算法”,有些算法会对区间进行从大到小的排序,称为排序算法。还有其他一些算法会用到大小的概念。

vector

常见用法、成员函数

int a[5]={1,2,3,4,5};
vector<int> v(a,a+5);//将数组的前五个数据来初始化容器
v.insert(v.begin()+2,13);//在begin+2的位置上插入13
v.erase(v.begin()+2);//删除位于begin()+2的元素
vector<int> v2(4,100);//初始化方式,有4个元素,都是100
v2.insert(v2.begin(),v.begin()+1,v.begin()+3);//将v的一段插入v2的开头
v.erase(v.begin()+1,v.begin()+3);//删除v上的一个区间

用vector实现二维数组

vector<vector<int> > v(3);//v有3个元素,每个元素都是vector<int>容器

deque

所有适用于vector的操作都适用于deque。deque还有push_front(将元素插入到前面)和pop_front(删除最前面的元素)操作,复杂度是O(1)。

list

双向链表,在任何位置插入删除都是常数时间,不支持随机存取。除了具有所有顺序容器都有的成员函数外,还支持8个成员函数:

push_front	在前面插入
pop_front	删除前面的因素
sort		排序
remove		删除和指定值相等的所有元素
unique		删除所有和前一个元素相同的元素(要做到元素不重复,则unique之前还要sort)
merge		合并两个链表,并清空被合并的那个
reverse		颠倒链表
splice		在指定位置前面插入另一链表的一个或多个元素,并在另一链表中删除被插入的元素

函数对象

若一个类重载了运算符“()”,则该类的对象就称为函数对象。

class MyAverage
{//定义类
public:
	double operator()(int a1,int a2,int a3){//重载了()的函数
		return (double)(a1+a2+a3)/3;
	}
};
MyAverage average;//函数对象
cout<<average(3,2,1);//等价于average.operator()(3,2,1)

STL中的函数对象类模板
以下模板可以用来生成函数对象:

equal_to
greater
less
......
头文件为<functional>
greater函数对象类模板:
template<class T>
struct greater:public binary_function<T,T,bool>{
	bool operator()(const T& x,const T & y) const{
		return x>y;//比较大小
	}
};

greater的引用
list有两个sort成员函数:

  1. void sort(); 将list中的元素按照“<”规定的比较方法升序排列
  2. template <class Compare> void sort(Compare op); 将list中的元素按op规定的比较方法升序排列。即要比较x,y大小时,看op(x,y)的返回值,为true则认为x小于y

在STL中使用自定义的大小关系
关联容器和STL中许多算法都是可以用函数或函数对象自定义比较器的。在自定义了比较器op的情况下,以下三种说法是等价的:

  1. x小于y
  2. op(x,y)返回值为true
  3. y大于x

关联容器

set\multiset\map\multimap
内部元素有序排列,新元素插入的位置取决于它的值,查找速度快。除了各个容器都有的函数外,还支持以下成员函数:

find	查找等于某个值的元素
lower_bound 查找某个下界
upper_bound 查找某个上界
equal_range 同时查找上界和下界
count	计算等于某个值的元素个数
insert	用以插入一个元素或一个区间

pair模板
map和multimap容器里放着的都是pair模板类的对象,且按first从小到大排列。构造函数用法实例:

p(pair<double,double>(5.5,4.4));//p.first=5.5,p.second=4.4

multiset

template<class Key,class Pred=less<Key>,class A=allocator<Key> >
class multiset{......}
Pred类型的变量决定了multiset中的元素,“一个比另一个小”是怎么定义的。
multiset运行过程中,比较两个元素x,y大小的做法就是生成一个Pred类型的变量,假定为op,若表达式op(x,y)
返回值为true,则x比y小。
Pred的缺省类型是less<Key>

less模板的定义:
template<class T>
struct less:public binary_function<T,T,bool>
{bool operator()(const T& x,const T& y){return x<y;} const;}
less模板靠<来比较大小

multiset的成员函数

iterator find(const T& val)
在容器中查找值为val的元素,返回其迭代器。找不到则返回end()

iterator insert(const T& val)
将val插入到容器中并返回其迭代器

int count(const T& val)
统计有多少个元素的值和val相等

iterator lower_bound(const T& val)
查找一个最大的位置it使得[begin(),it)中所有的元素都比val小

iterator upper_bound(const T& val)
查找一个最小的位置it使得[it,end())中所有的元素都比val大

pair<iterator,iterator> equal range(const T& val)
同时球的lower_bound和upper_bound

iterator erase(iterator it);
删除It指向的元素,返回其后面的元素的迭代器(Visual Stdio 2010上是这样,C++标准和Dev C++不是这样)

multiset的用法

#include <set>//头文件
using namespace std;
class A{};
int main()
{
	multiset<A> a;//等价于multiset<A,less<A>> a
	a.insert(A());//error,插入元素时,multiset会将被插入元素和已有元素进行比较
				  //less模板是用<进行比较的,所以这要求A的对象能用<比较,即适当重载了<

set

template<class Key,class Pred=less<Key>,class A=allocate<Key>>
class set{......}
插入set中已有的元素时,忽略插入
#include <iostream>
#include <set>
using namespace std;
int main()
{
	typedef set<int>::iterator IT;
	int a[5]={3,4,6,1,2};
	set<int> st(a,a+5);//st这里是1 2 3 4 6
	pair<IT,bool>result;
	result=st.insert(5);//st变成1 2 3 4 5 6
	if(result.second)
		cout<<* result.first<<"inserted"<<endl;//5成功插入,输出5 inserted
	if(st.insert(5).second)
		cout<<* result.first<<endl;
	else cout<<* result.first<<"already exists"<<endl;//5被重复插入,所以插入失败
	
	pair<IT,IT> bounds=st.equal_range(4);
	cout<<*bounds.first<<","<<* bounds.second;//输出4,5
	return 0;
}	

map和multimap

multimap

multimap中的元素由<关键字,值组成,每个元素是一个pair对象,关键字就是first成员变量,其类型为Key
multimap允许多个元素的关键字相同。元素按照first成员变量从小到大排列,缺省情况下用less<Key>定义的小于关系。
template<class Key,class T,class Pred=less<Key>,class A=allocate<T>>
class multimap{
	...
	typedef pair<const Key,T>value_type;
	......
};//Key即关键字的类型

map
map中的元素都是pair模板类对象,关键字各不相同。元素按照关键字从小到大排列,缺省情况下用less,即<定义小于。

template<class Key,class T,class Pred=less<Key>,class A=allocator<T>>
class map{
	......
	typedef pair<const Key,T> value_type
	......
};

map的[ ]成员函数
若pairs为map模板类的对象;则pairs[key]返回对关键字等于key的元素的值(second成员变量)的引用。若没有关键字为key的元素,则会往pairs里插入一个关键字为key的元素,其值用无参构造函数初始化,并返回其值的引用。

map<int,double>pairs;
pairs[50]=5;
//会修改pairs中关键字为50的元素,使其值为5,若不存在关键字为50的元素,则插入此元素并使其值为5

容器适配器

容器适配器都有empty()函数用于判断适配器是否为空,size()函数用于返回适配器中元素的个数
stack
栈,后进先出,只能插入和删除,访问栈顶元素。可以用vector\list\deque实现,缺省情况下用deque实现。用vector和deque实现比list性能好。

template<class T,class Cont=deque<T> >
class stack{......};
可进行push\pop\top(返回栈顶元素的引用)等操作

queue
队列,和stack类似,可以用list和deque实现,缺省条件下用deque实现。push发生在队尾。pop和top发生在队头,先进先出。有back成员函数可以返回队尾元素的引用

template<class T,class Cont=deque<T> >
class queue{
	......
};

priority_queue
和queue类似,可以用vector和deque实现,缺省条件下用vector实现。通常用堆排序技术实现,保证最大的元素总是在最前面。即执行pop操作时,删除的是最大的元素,执行top时返回的是最大的元素的引用。默认的元素比较器是less

template <class T,class Container=vector<T>,class Compare=less<T> >
class priority_queue;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值