一、vector
vector
容器内的元素可以通过下标访问,也可以通过迭代器访问。vector
迭代器的定义方式是vector<typename>::iterator it
,通过*it
就可以访问vector
里面的元素了。vector
的迭代器允许直接加上一个整数,比如it + 3
这种形式,除了string
和deque
容器外,其余的常用STL容器都不支持这种写法。
begin()
函数取容器的首元素地址,end()
函数取容器的尾元素地址的下一个地址,这两个函数返回的数据都是迭代器类型的。除了可以直接定义迭代器变量,C++11标准还可以用auto
关键字让程序自己推断变量类型。
auto it1 = vi.begin();
auto it2 = vi.end();
insert(it,x)
用来向vector
的任意迭代器it
处插入一个元素x
,时间复杂度为O(N)
。
erase()
有两种用法:删除单个元素、删除一个区间内的所有元素。时间复杂度均为O(N)
。erase(it)
删除迭代器it
处的元素,erase(first, last)
删除[first, last)
区间内的所有元素。
一旦内存重新分配,vector
元素相关的所有reference
、pointer
和iterator
都会失效。
二、set
set
是一个内部自动有序且不含重复元素的容器。
set
容器内的元素不能通过数组下标来访问,一般是通过迭代器访问,当然也还可以用for(auto i : st)
的方式进行遍历。
find(value)
返回set中对应值为value
的迭代器,内部用红黑树实现,时间复杂度为O(logN)
,若找不到则返回set.end()
。
erase(it)
删除迭代器it
所指的元素;erase(value)
删除值为value
的元素;erase(first, last)
删除区间[first, last)内的所有元素。
count(value)
返回值为value
的元素的数目。
三、string
string
的insert()
函数有多种写法,这里给出两个常用的写法,时间复杂度为O(N)。insert(pos,string)
,在pos
号位置插入字符串string
;insert(it0,it1,it2)
,it0
为原字符串的欲插入位置,it1
和it2
为待插字符串的首尾迭代器,用来表示串[it1,it2)
将被插在it0
的位置上。
erase(it)
用于删除迭代器it
所指向的元素;erase(first, last)
用于删除[first, last)
区间的元素,其中first
和last
都是迭代器;erase(pos,length)
删除从位置pos
开始,长为length
的字符串。
replace(pos,len,str2)
把str
从pos
号位开始、长度为len
的子串替换为str2
;replace(it1,it2,str2)
把[it1, it2)
范围内的子串替换为str2
。
四、map
map
容器内的元素按关键字有序,且不含重复的元素,每个元素为一个键值对。
map
容器内的元素可以通过下标访问或通过迭代器访问。map[key]
是通过下标访问,若map
中没有键为key
的元素,,则map
会自动创建一个键为key
的元素,并根据value
的类型返回一个默认值,具体如下:
int, float, double
: 0
string
: ""
char
: \0
stl容器
: 空容器
map
可以使用it->first
来访问键,使用it->second
来访问值,其中it
是迭代器。
find(key)
返回键为key
的映射的迭代器,时间复杂度为O(logN)
。
erase()
有两种用法:删除单个元素、删除一个区间内的所有元素。erase(it)
删除迭代器it
所指向的元素;erase(key)
删除键为key
的映射;erase(first, last)
删除区间[first, last)
内的所有元素。
五、queue
由于队列本身就是一种先进先出的限制性数据结构,因此在STL中只能通过front()
来访问队首元素,或是通过back()
来访问队尾元素。
pop()
令队首元素出队。push(x)
将x
入队。
六、priority_queue
priority_queue
又称为优先队列,其底层是用堆来进行实现的。在优先队列中,队首元素一定是当前队列中优先级最高的那一个。
优先队列中没有front()
函数和back()
函数,而只能通过top()
函数来访问队首元素(也可以称为堆顶元素),也就是优先级最高的元素。
当是基本数据类型时,下面两种优先队列的定义是等价的。
priority_queue<int> q;
priority_queue<int, vector<int>, less<int> > q;
less<int>
表示数字大的优先级大,而greater<int>
表示数字小的优先级大。
当数据类型是结构体时,就需要重载小于号<
,如下面的代码所示。
struct fruit{
string name;
int price;
friend bool operator < (fruit f1, fruit f2) {
return f1.price < f2.price;
}
}
七、pair
pair
实际上可以看作一个内部有两个元素的结构体,且这两个元素的类型是可以指定的。
如果想在定义pair
时进行初始化,只需要跟上一个小括号,里面填写两个想要初始化的元素即可。
pair<string, int> p("csdn",1);
如果想要在代码中临时构建一个pair
,有如下两种方法。
- 将类型定义写在前面,后面用小括号内两个元素的方式
pair<string, int>("csdn", 1);
- 使用自带的
make_pair
函数。
make_pair("csdn", 1);
对pair
的访问类似于结构体的访问,因为pair
中只有两个元素,所以访问应该为p.first
和p.second
。
两个pair
类型数据可以直接使用==
、!=
、<
、<=
、>
、>=
比较大小,比较规则是先以first
的大小作为标准,只有当first
相等时才去判别second
的大小。
pair
可以作为map
的键值对来进行插入,比如mp.insert(make_pair("csdn", 1));
八、array
array
的定义如下,定义时必须指明类型和大小,且大小一旦指定就不能再更改。
array<int, 10> a1;
array<int ,6> a2 = {1,2,3};
a[idx]
会返回索引idx
所指的元素(不检查范围);a.at(idx)
返回索引id
所指的元素(如果idx
超出范围就抛出异常);a.front()
返回第一个元素;a.back()
返回最末元素。
九、deque
deque
是双向队列,音同deck
,能在头尾两端进行快速安插和删除。对deque
的访问会比其他STL
稍微慢一点,但是deque
的内存重分配要优于vector
(元素插入或删除可能会导致内存重分配)。
deque
的大部分特性都和vector
相同,比如支持数组下标访问,迭代器加数字等。主要的区别在于deque
多了两个操作:push_front(elem)
在头部插入elem
的一个拷贝,pop_front()
移除第一个元素。
十、list
list
使用一个doubly linked list(双向串列)来管理元素,类似于双向链表。
list
在几个主要方面与array
、vector
或deque
不同。
list
不支持随机访问,如果你要访问第5个元素,就得顺着串链逐一爬过前4个元素。所以,在list
中随机巡访任意元素是很缓慢的行为。然而你可以从两端开始航行整个list
,所以访问第一个或最末一个元素的速度很快。- 任何位置上(不只两端)执行元素的安插和移除都非常快,始终都是常量时间内完成,因为无须移动任何其它元素。实际上内部只是进行了一些
pointer
操作而已。 - 安插和删除动作并不会造成指向其它元素的各个
pointer
、reference
和iterator
失效。
front()
函数和back()
函数分别用于返回第一个元素和最后一个元素。
凡是用到随机访问迭代器的算法(所有用来操作元素顺序的算法——特别是排序算法——都归此类)你都不能调用他们来处理list
,不过你可以拿list的特殊成员函数sort()
取而代之。
push_back()
、pop_back()
、push_front()
、pop_front()
。