c++ STL模板(一)

时间:2022-04-24 17:18:38

一.sort函数

1、头文件:#include < algorithm>;

2、它使用的排序方法是类似于快排的方法,时间复杂度为n*log2(n);

3、Sort函数有三个参数:(第三个参数可不写)

(1)第一个是要排序的数组的起始地址。

(2)第二个是结束的地址(最后一位要排序的地址的下一位地址)。

(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。升序:sort(begin,end,less<data-type>());降序:sort(begin,end,greater<data-type>())。

二.lower_bound函数

头文件: #include<algorithm>

函数模板: 如 binary_search()

函数功能:  函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!

返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置

三.upper_bound函数

头文件:#include<algorithm>

函数模板: 如binary_search()

函数功能:函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置。

同样,如果插入元素大于数组中全部元素,返回的是last。(注意:数组下标越界)

返回查找元素的最后一个可安插位置,也就是“元素值>查找值”的第一个元素的位置。

四.不定长数组:vector

头文件:#include<vector>

函数功能:vector就是一个不定长数组。不仅如此,它把一些常用的操作封装在了vector类型内部。例如,若a是一个vector,可以用a.size()读取它的大小,a.resize()改变大小,a.push_back()向尾部添加元素,a.pop_back()删除最后一个元素,a.empty()测试是否为空。

vector是一个模板类,所以需要用vector<int> a或者vector<double> b这样的方式来声明一个vector。vector<int>是一个类似于int a[]的整型数组。vector看上去像“一等公民”,因为他们可以直接赋值,还可以作为函数的参数或返回值,而无须像传递数组那样另外用一个变量指定元素个数。

五.集合:set

头文件:#include<set>

函数功能:set就是数学上的集合——每个元素最多只出现一次。和sort一样,自定义类型也可以构造set,但同样必须定义“小于”运算符。set<string> dict用来定义一个string集合,dict.insert(buf)用来插入一个字符串(由于string已经定义了“小于”运算符,直接使用set保存字符串集合即可)由于set中元素会按从小到大排序这一性质,则set中的字符串会按从小到大排好序。

六.映射:map

头文件:#include<map>

函数功能:map就是从键(key)到值(value)的映射。因为重载了[ ]运算符,map像数组的“高级版”。例如可以用一个map<string,int>month_name来表示“月份名字到月份编号”的映射,然后用month_name["July"]=7这样的方式来赋值。

为了使用方便,可以对模板类进行一下类型定义,

typedef map<int,CString> UDT_MAP_INT_CSTRING;

UDT_MAP_INT_CSTRING enumMap;

自动建立Key - value的对应。key 和 value可以是任意你需要的类型。

根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。

快速插入Key -Value 记录,insert()函数。

获取map的大小,size()函数。

快速删除记录

根据Key 修改value记录。

用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了。

用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器。

查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,

分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator.

移除某个map中某个条目用erase(),该成员方法的定义如下:

iterator erase(iterator it);//通过一个条目对象删除

iterator erase(iterator first,iterator last)//删除一个范围

size_type erase(const Key&key);//通过关键字删除

map中的元素是自动按Key升序排序,所以不能对map用sort函数;这里要讲的是一点比较高深的用法了,排序问题,STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int 型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过 不去,所以需要定义一个“小于”运算符“。

还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL Algorithm也可以完成该功能,建议用map自带函数,效率高一些。

下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的 数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),我想大家应该知道,这些地方 很费内存了吧,不说了……

map的基本操作函数:

C++ maps是一种关联式容器,包含“关键字/值”对

begin()         返回指向map头部的迭代器

clear()        删除所有元素

count()         返回指定元素出现的次数

empty()         如果map为空则返回true

end()           返回指向map末尾的迭代器

equal_range()   返回特殊条目的迭代器对

erase()         删除一个元素

find()          查找一个元素

get_allocator() 返回map的配置器

insert()        插入元素

key_comp()      返回比较元素key的函数

lower_bound()   返回键值>=给定元素的第一个位置

max_size()      返回可以容纳的最大元素个数

rbegin()        返回一个指向map尾部的逆向迭代器

rend()          返回一个指向map头部的逆向迭代器

size()          返回map中元素的个数

swap()           交换两个map

upper_bound()    返回键值>给定元素的第一个位置

value_comp()     返回比较元素value的函数

七.栈、队列与优先队列

1.栈:头文件:<stack>;

用stack<int> s 方式声明一个栈;

用push(),pop()实现元素的入栈,出栈操作,top()取栈顶元素(但不删除)。

2.队列:头文件:<queue>;

用queue<int> s 方式声明一个队列;

用push(),pop()实现元素的入队和出队操作,front()取队首元素(但不删除)。

3.优先队列:是一种抽象数据类型(Abstract Data Type,ADT),行为类似队列,但先出的元素不是先进的元素,而是队列中优先    级最高的元素。

头文件:<queue>;

用priority_queue<int> qp  来声明,这个pq是一个“越小的整数优先级越低的优先队列”;

用push(),pop()实现元素的入队,出队操作,top()取队首元素(但不删除)。

自定义类型也可以组成优先队列,但必须为每个元素定义一个优先级。这个优先级并不需要一个确定的数字,只需要能比较大小即可。只要元素定义了“小于”运算符,就可以使用优先队列。对于一些常见的优先队列,STL提供了更为简单的定义方法,例如,“越小的整数优先级越大的优先队列”可以写为"priority_queue<int,vector<int>,greater<int> >pq"。Attention:最后两个“>"不要写在一起,否则会被很多(但不是所有)编译器误认为是">>"运算符。