STL容器

Posted pedesis

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL容器相关的知识,希望对你有一定的参考价值。

iterator 迭代器

  这就像是STL容器的指针,可以用星号"*"操作符解除引用

  我们就先用vector举个例子

vector<int>::iterator it;//声明方式 it是迭代器名

//下面这两种遍历方式是等价的
for(int i=0;i<v.size();i++)
    cout<<v[i]<<endl;
for(vector<int>::iterator it=v.begin();it!=v.end();it++)
    cout<<*it<<endl;

vector

  头文件:<vector>

  向量,个人习惯称为动态数组,因为它相当于一个不定长的数组,当数组长度达到目前最大长度的时候,会将数组的容量扩容至原来的两倍

  初始化

   1. vector<类型> 名称 //后面的容器都可以这样命名

   2. vector<类型> 名称(最大容量)

   3. vector<类型> 名称(最大容量,初始所有值)

   4. vector<vector<类型> > 名称 //二维向量

  v.size()  容器的实际长度   v.empty()  判断容器是否为空(bool)  O(1)

   由于STL容器基本都支持这些操作,所以后面不会再提及

  v.push_back(x)  在数组末尾插入元素x   v.pop_back()  在数组末尾删除一个元素

   假设vector的实际长度为n,最大长度为m,当n=m时,会扩展一倍的容量,当n<=m/4时,会释放一半的空间,因此均摊后插入和删除的时间复杂度都近似O(1)(实际上vector的反复扩容在使用中是很耗时的)

  v.clear()  清空容器(不会释放内存)  O(n)

  v.erase(iterator_x)  删除迭代器位置x上的元素

  v.erase(iterator_x,iterator_y)  删除迭代器位置[x,y)上的元素  O(n)

   调用该函数后,vector后面的元素会前移,所以在遍历时使用后通常会将迭代器自减

  v.begin()  返回数组第一个元素的迭代器  O(1)

  v.end()  返回数组最后一个元素后的迭代器  O(1)

   所有的容器都可以视为一个前闭后开的结构,因此end函数返回的是vector尾部的边界,该位置无元素

  v.front()  返回数组的第一个元素   v.back()  返回数组的最后一个元素  O(1)

   前者等价于 *v.begin() 和 v[0],后者等价于 *--v.end() 和 v[v.size()-1]

  v.reserve(x)  增加容量到大于或等于x的值 若x小于实际长度则无意义  O(n)

  v.swap(vector_x)  与另一个同类型vector交换数据  O(1)

  v1=v2  两个vector之间可直接用"="号赋值  O(n)

stack

  头文件:<stack>

  栈,按照先进后出的原则存储数据,没什么特殊的函数,手写十分方便,跑得也更快,所以这个容器就不多讲了

queue

  头文件:<queue>

  队列,按照先进先出的原则存储数据

  q.push(x)  在队尾插入元素  O(1)

  q.pop()  删除队首元素  O(1)

  q.front()  返回队首元素  O(1)

  q.back()  返回队尾元素  O(1)

priority_queue

  头文件:<queue>

  优先队列,相当于一个大根二叉堆(但不支持删除堆中任意元素),每次取出优先级最高的元素

  pq.push(x)  在堆中插入元素  O(log n)

  pq.pop()  删除堆顶元素  O(log n)

  pq.top()  返回堆顶元素  O(1)

  实现小根堆

priority_queue<int,vector<int>,greater<int> > pq;

//或重载运算符 
struct Data{
    int num;
    bool operator< (Data rhs) const{
        return num>rhs.num;
    }
};
priority_queue<Data> pq;

deque

  头文件:<deque>

  双向队列,支持在两端高效插入或删除元素,与vector相比,它在头部增删元素仅需要O(1)的时间,与queue相比,它像数组一样支持随机访问

  []  访问元素  O(1)

  dq.push_back(x)  从队尾入队  O(1)

  dq.push_front(x)  从队头入队  O(1)

  dq.pop_front()  从队头出队  O(1)

  dq.pop_back()  从队尾出队  O(1) 

  dq.begin()/end()  返回队头/队尾迭代器  O(1)

  dq.front()/back()  返回队头/队尾元素  O(1)

 

list

  头文件:<list>

  双向链表,将元素储存在链表中,允许快速的插入和删除,但是随机访问却比较慢,所以它经常用于内部任意位置(即除了头尾以外的其他位置)元素的频繁增删

  l.insert(iterator_p,x)  在p位置插入一个x元素  O(1)

  l.insert(iterator_p,n,x)  在p位置插入n个x元素  O(n)

   这里的O(n)指n的大小,同理后面有关区间的操作,O(n)是指区间长度

  l.insert(iterator_p,iterator_x,iterator_y)  在p位置插入[x,y)中的元素  O(n)

  l.push_back(x)  在链表尾部插入元素x  O(1)

  l.push_front(x)  在链表开头插入元素x  O(1)

  l.pop_back()  删除链表尾部元素  O(1)

  l.pop_front()  删除链表开头元素  O(1)

  l.begin()/end()  返回首尾迭代器  O(1)

  l.front()/back()  返回首尾元素  O(1)

  l.clear()  清空  O(n)

  l.erase(iterator_x)  删除位置x的元素  O(1)

  l.erase(iterator_x,iterator_y)  删除位置[x,y)的元素  O(n)

  l.remove(x)  删除所有与x匹配的元素  O(n)

  l.swap(list_x)  与另一个list交换数据  O(1)

  l.merge(list_x)  将升序链表l与x归并为升序链表l,链表x变为空  O(n)

  l.reverse()  将链表翻转  O(n)

  l.unique()  除去链表中的重复元素(除第一个)  O(n)

  l.sort()  以升序将链表排序  O(n log n)

set

  头文件:<set>

  有序集合,内部元素保持有序(默认从小到大)且不重复(multiset可以包含重复元素)

  s.insert(x)  向集合中插入元素  O(log n)

  s.clear()  清空  O(n)

  s.erase(x)  删除元素x  O(log n)

  s.erase(iterator_x)  删除迭代器指向的元素  O(log n)

  s.begin()/end()  返回集合首尾迭代器  O(1)

  s.find(x)  返回元素x的迭代器 若不存在返回s.end()  O(log n)

  s.lower_bound(x)  返回大于等于x的最小元素的迭代器  O(log n)

  s.upper_bound(x)  返回大于x的最小元素的迭代器  O(log n)

  s.count(x)  返回元素x的个数  O(log n)

map

  头文件:<map>

  映射,表示键(key)到值(value)的映射,key保持有序(默认从小到大),这个容器强的地方在于支持很多数据类型之间的映射,甚至字符串和结构体

  初始化  map<key,value> m;

  []  插入值和获取值  O(log n)

  m.clear()  清空  O(n)

  m.erase(x)  删除key为x的元素  O(log n)

  m.erase(iterator_x)  删除迭代器指向的元素  O(log n)

  m.begin()/end()  返回首尾迭代器  O(1)

  m.find(x)  返回key为x的元素的迭代器 若不存在返回m.end()  O(log n)

  m.count(x)  返回key为x的元素个数(非0即1)  O(log n)



以上是关于STL容器的主要内容,如果未能解决你的问题,请参考以下文章

STL容器自定义内存分配器

c++ 容器含义

STL源代码剖析 容器 stl_stack.h

STL源代码剖析 容器 stl_deque.h

STL源代码剖析 容器 stl_vector.h

STL 容器的概念