STL常用容器

常用STL

一. stack

1.简介: 是最常用的STL容器,需要加 <stack> 头文件

2.定义: stack <type> name;

3.可用函数:

  1. size:大小
  2. empty:是否为空
  3. push:栈顶插入
  4. pop:栈顶取出
  5. top:栈顶元素

二. queue

1.简介: 是最常用的STL容器,需要加 <queue> 头文件

2.定义: queue <type> name;

3.可用函数:

  1. size:大小
  2. empty:是否为空
  3. push:队尾插入
  4. pop:队首取出
  5. front:队头元素
  6. back:队尾元素

均可通过 " . + 函数名" 调用。

三. priority_queue

1.简介: 一个大/小根堆(默认大根堆), 需加 <queue> 头文件

2.定义: proirity_queue <Type,Container,Functional> name;

3.可用函数:

  1. size:大小
  2. empty:是否为空
  3. push:堆插入
  4. pop:堆顶取出
  5. top:堆顶元素

4.关于priority_queue中元素的比较:

模板申明带3个参数:Type, Container, Functional,其中Type 为数据类型,Container为保存数据的容器,Functional 为元素比较方式。

  Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector。

如果缺省后两个参数, 则默认大根堆。

5.将大根堆转化为小根堆

① 将三个参数全部填上, STL里面定义了一个仿函数greater<>,基本类型可以用这个仿函数声明小顶堆。

priority_queue<int, vector<int>, greater<int> > q; //一个小根堆

② 使用 pair 类型, pair 中first存所需比较元素的相反数,second中存放需要元素。

priority_queue < pair<int, int> > q;

③ 使用结构体重载小于号转化,此方法可以存较多元素, 实现较复杂的操作。

struct node
{
    int x;
    bool operator < (const node & b) const
    {
        return x > b.x; //将小于号重载为大于号即可
    }
};

priority_queue <node> q;

另:后两者常用于Dijstra求最短路。

四. deque

1.简介: 一个双端队列, 需加 <deque> 头文件

2.定义: deque <type> name;

3.可用函数:

  1. []:随机访问
  2. begin/end:头/尾 迭代器
  3. front/back:头/尾 元素
  4. push_back:从队尾插入
  5. push_front:从队头插入
  6. pop_back:从队尾出队
  7. pop_front:从队头出队
  8. clear:将队列清空

注:deque支持随机访问,时间复杂度 \(O(n)\)

五. vector

1.简介: 一个长度可变的数组, 需加 <vector> 头文件

2.定义: vector <type> name;

3.可用函数:

  1. [ ]:随机访问
  2. size:大小
  3. empty:是否为空
  4. clear:将vector清空
  5. begin/end:头/尾 迭代器
  6. front/back:头/尾 元素
  7. push_back/pop_back:从尾插入/删除
  8. resize:s.resize(siz),将名为s的vector的size定义为siz
  9. at: 功能类似于map和set的find函数,越界时会抛出错误,可以当[]使用,但会更慢。

4.对vector中元素进行逐个访问:

使用iterator、auto 或 下标

vector <int> vec;
for (vector <int> ::iterator it = vec.begin(); it != vec.end(); ++ it)
{
    cout << *it << endl; 
}

for (auto a : vec)
{
    cout << a << endl;
}

for (int i = 0; i < vec.size(); ++ i)
{
    cout << vec[i] << endl;
}

六. set(multiset)

1.简介: 一个集合(封装好的平衡树(红黑树))。

set , multiset 需加 <set> 头文件

set默认升序,如需降序这么写:

set <int, greater<int>> st;

副: set 为有序集合, multiset 为有序多重集合, unordered_set(基于Hash表) 很少用,故不多赘述。

2.定义: set <type> name;

3.可用函数:

  1. size:大小

  2. empty:是否为空

  3. clear:将集合清空

  4. begin/end:头/尾 迭代器

  5. front/back:头/尾 元素

  6. insert:向集合中插入元素,时间复杂度$ O(log{n}) $ (副: multiset 可以重复插入元素)

  7. find:s.find(x)会于集合中查找等于x的元素,并返回指向该元素的 迭代器 , 若不存在,则返回 s.end(), 时间复杂度$ O(log{n}) $

  8. lower_bound/upper_bound:用法与find类似。

    ①s.lower_bound(x) 查找 $\geqslant x $ 的元素中最小的, 并返回指向该元素的迭代器

    ②s.upper_bound(x) 查找 $> x $ 的元素中最小的, 并返回指向该元素的迭代器

  9. erase: 删除

    设it为一个迭代器, s.erase(it) 从s中删除迭代器it指向的元素, 时间复杂度 $ O(log{n}) $
    设x为一个元素, s.erase(x) 从s中删除所有等于x的元素, 时间复杂度 $ O(k + log{n}) $ (k 为被删除的元素个数)
    如果想从multiset中删除掉至多1个等于x的元素,可以执行

    if((it = s.find(x)) != s.end()) s.erase(it);
    
  10. count: s.count(x) 返回集合s中等于x的元素个数, 时间复杂度$ O(k + log{n}) $ (k 为元素x的个数)

4.对集合中元素的遍历:

①建立迭代器

for(set <int> ::iterator it = s.begin(); it != s.end(); ++it)
{
    cout << *it << endl; 
}

②使用auto

for (auto x : s)
{
    cout << x << endl;
}

七. map(unordered_map)

1.简介: 一个键值对kay-value的映射(实现为一棵以key为关键码的红黑树)。map的key和value可以是任何类型, 其中k必须定义“\(<\)”运算符。

map 需加 <map> 头文件, unordered_map 加 <unordered_map> 头文件。

2.定义: map <key_type,value_type> name;

副: multimap 与 map 的区别类似与 multiset 和 set, 只是在能否重复上不同,故不多赘述。

3.可用函数:

  1. size:大小
  2. empty:是否为空
  3. clear:将集合清空
  4. begin/end:头/尾 迭代器
  5. insert/erase:插入/删除 与set类似, insert的参数为 pair <key_type,value_type>, erase的参数可以为pair或迭代器
  6. find:h.find(x) 在名为h的map中查找key为x的二元组, 并返回指向该二元组的迭代器。 若不存在,则返回 h.end()。时间复杂度$ O(log{n}) $
  7. []操作符:h[key]返回key映射到的value的引用, 时间复杂度$ O(log{n}) $

八. bitset

1.简介: 可看作一个多位二进制数,每八位占用1个字节,相当于采用了状态压缩的二进制数组,并支持基本的位运算操作(~, &, |, ^, >>, <<, ==, !=)。

2.定义: bitset <length> name;

3.可用函数:

  1. []:随机访问

  2. count:s.count() 返回有多少位为1, 时间复杂度$ O(n) $

  3. any/none:

    ①若s所有位都为0, s.any()返回false, s.none()返回true。

    ②若s所有位都为0, s.any()返回false, s.none()返回true。

  4. set:s.set()将所有位变为1,s.set(k, v)将s的第k位改为v。

  5. reset:s.reset()将所有位变为0,s.reset(k)将第k位改为0。

  6. flip:s.flitp()将s的所有位取反,s.flitp(k)将s的第k位取反。

另副一些方便的STL函数

  1. emplace()

    在对STL中vector, set, queue进行插入时(如:insert(), push_back())会先对对象进行初始化构造, 后插入时再进行一次拷贝操作,时间复杂度较高。而emplace可以直接插入,常数较小。

注意:只有把emplace当做一个构造函数时才有优势,将构造好的元素插入时两者无差别。

副:

insert()/push()  -> emplace()
push_back() -> emplace_back()
  1. distance()

    是一个常用的迭代器操作函数,用来计算两个迭代器之间的距离,它可以接受任何类型的迭代器

Updata on 11.14: stl容器是可以直接修改其中内容的,但不会修改原变量的值。我之前一直以为放到栈和队列里的数据不能直接改

我是SB bs。

完~~

posted @ 2022-10-06 20:25  Eakang  阅读(305)  评论(17编辑  收藏  举报