stl容器使用和算法简介

STL容器特征总结

竞赛重点:底层、内存、增删查复杂度、迭代器、优缺点、适用场景

序列式容器(元素按存放顺序排列,可存重复)

vector string deque


关联容器(红黑树,自动有序,<algorithm>的sort不需要再排)

map multiset multimap


无序关联容器(哈希表,C++11)

unordered_set unordered_map


容器适配器(包装别的容器,没有迭代器!不能begin() end()遍历

stack queue priority_queue


1.string字符串

  • 底层:连续char数组,和vector几乎一样

  • 支持[]随机访问,+拼接

  • 迭代器:随机访问迭代器

    #include

    // 数字转字符串
    string s1 = to_string(123);
    string s2 = to_string(3.14);

    // 字符串转数字
    int num = stoi("123");
    double dou = stod("3.14");
    long long ll = stoll("123456");

    /string 头尾/
    str.front(); //第一个元素
    str.back(); //最后一个元素

    /string 分割/
    str.substr(2, 5); //返回从索引2开始的五个元素组成的字符串

    /string 插入/
    str.push_back('a'); //在尾部插入一个字符
    str.insert(str.begin(), 'a'); // 在开头前插入 'a'

    /string 容量/
    str.size()
    str.length()

    /string 遍历/
    for(int i = 0; i < str.size(); i ++ ) //索引遍历
    for(string::iterator iter = str.begin(); iter != str.end(); iter ++ ) //迭代器遍历
    for(auto &x : str) //迭代器另一种便捷方法

    /string 排序/
    sort(str.begin(), str.end());

    /sting 查找/
    int pos = s.find("world"); // 正向查找
    s.find(str,index); //返回从index开始str第一次出现的位置, 找不到就返回
    用find查找重复或不重复的连续目标字符串
    string target="2020";
    string s;
    cin>>s;
    int ans=0;
    size_t pos=s.find(target);
    while(pos!=string::npos)
    {
    ans++;
    pos=s.find(target,pos+1/n);
    }
    cout<<ans<<endl;

    /string 删除/
    str.pop_back(); //删除最后一个元素
    s.erase(unique(s.begin(), s.end()), s.end()); //删除排序后的重复字符
    str.erase(str.begin()); //删除迭代器指向元素
    str.erase(str.begin()+1, str.end()-2); //删除指定区间的元素
    str.erase(1, 6); //删除从索引(1)开始的n(6)个字符

    /string 替换/
    str.replace(str.begin(), str.begin() + 5, "boy"); //替换迭代器指定的区间
    str.replace(6, 5, "girl"); //替换索引指定的区间,从下标6开始的五个元素

    /string 判空/
    str.empty() //返回布尔值

    /string 清空/
    str.clear();

    /string 迭代器/
    string::iterator iter //一个string的迭代器
    str.begin() //指向str第一个元素位置的迭代器
    str.end() //指向str最后一个元素后一个位置的迭代器

    /string 比较/
    str1 < str2 //字典序比较,<、<=、==、>、>=都可以用
    str1.compare(str2) //相等为0,str1>str2为1,反之-1

    /string 拼接/
    str1.append(str2); //str1str2
    str1 = str1 + str2; //str1str2

    /string 生成/
    string str("123"); //"123"
    string str(3,'1'); //"111"
    string str = "123"; //"123"

2. vector<T> 动态数组

  • 底层:连续内存数组

  • 访问:支持下标[]随机访问, ( O ( 1 ) ) (O(1)) (O(1))

  • 尾部push_back/pop_back: ( O ( 1 ) ) (O(1)) (O(1))

  • 中间/头部插入删除: ( O ( n ) ) (O(n)) (O(n)),需要搬移元素

  • 迭代器:随机访问迭代器 ,支持it+5、it-2、< >

  • 会扩容,扩容会拷贝数据,迭代器会失效

  • ✅适合:大量随机访问,尾部增删;不适合频繁中间插入删除

    #include

    /vector 头尾/
    vct.front(); //第一个元素
    vct.back(); //最后一个元素

    /vector 遍历/
    for(int i = 0; i < vct.size(); i ++ ) //索引遍历
    for(vector::iterator iter = vct.begin(); iter != vct.end(); iter ++ ) //迭代器遍历
    for(auto &x : vct) //迭代器另一种便捷方法

    /vector 排序/
    sort(vct.begin(), vct.end());

    /vector 插入/
    vct.push_back(2); //在尾部插入一个2
    vct.insert(vct.begin(), 2); //在指定位置前面插入一个元素

    /vector 删除/
    vct.pop_back();
    vct.erase(vct.begin());
    vct.erase(vct.begin()+1, vct.end()-2);
    v.erase(unique(v.begin( ),v. end( )), v.end( )); //对vector进行排重

    v.erase(remove(v.begin( ), v.end( ), value), v.end( )); //删除vector中值为value的元素

    /vector 迭代器/
    vector::iterator iter //一个vector的迭代器
    vct.begin() //指向vct第一个元素位置的迭代器
    vct.end() //指向vct最后一个元素后一个位置的迭代器

    /vector 容量/
    vct.size()

    /vector 判空/
    vct.empty() //返回布尔值

    /vector 清空/
    vct.clear();

vector二维

复制代码
vector<vector<int>> v;//空二维 vector(先定义再赋值)


vector<vector<int>> v(3);// 3行,每行都是空vector


vector<vector<int>> v(3, vector<int>(4, 10));// 3行4列,所有元素 = 10


vector<vector<int>> v(3, vector<int>(4, 10));// 3行4列,所有元素 = 10


int n = 3, m = 4;
vector<vector<int>> v(n, vector<int>(m, 0));//统一初始化 N 行 M 列


//遍历方式

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

3. deque<T> 双端队列

  • 底层:分段数组,不整体连续

  • 访问:支持下标随机访问 ( O ( 1 ) ) (O(1)) (O(1))

  • 头部、尾部插入删除都很快 (O(1))

  • 中间插入删除 ( O ( n ) ) (O(n)) (O(n))

  • 迭代器:随机访问迭代器

  • ✅适合:两头频繁增删,比如滑动窗口单调队列

    #include

    /deque 生成/
    deque dq;

    /deque 头尾/
    dq.front();
    dq.back();

    /deque 迭代器/
    dq.begin()
    dq.end()

    /deque 插入/
    dq.push_front(2); //头插入
    dq.push_back(2); //尾插入

    /deque 删除/
    dq.pop_front(); //头删除
    dq.pop_back(); //尾删除

    /deque 容量/
    dq.size();

    /deque 判空/
    dq.empty()

    /deque 清空/
    dq.clear();

4. set<T>

  • 底层:红黑树

  • 元素自动升序、去重,不能存重复值

  • 查找、插入、删除: O ( log ⁡ n ) O(\log n) O(logn)

  • 迭代器:双向迭代器,只可++ --不能it+k

  • ❗迭代器指向的值不能修改(*it=5编译报错)

  • .find(x)找不到返回.end()

    #include

    /set 生成/
    set st; // 整数集合
    set st2; // 字符集合
    set st3; // 字符串集合
    set st4; // 浮点数集合

    /set 迭代器/
    set::iterator iter
    st.begin()
    st.end()

    /set 某元素个数/
    st.count(2); //判断存在

    /set 插入/
    st.insert(2); //插入一个元素

    /set 容量/
    st.size()

    /set 删除/
    st.erase(st.begin()); //删除迭代器指向元素
    st.erase(2); //删除所有为2的元素

    /set 查找/
    st.find(2) //从前往后找,若找到,返回指向该处的迭代器;反之,返回迭代器st.end()
    st.lower_bound(x) //二分查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器。
    st.upper_bound(x) //二分查找大于x的元素中最小的一个,并返回指向该元素的迭代器。

    /set 判空/
    st.empty() //返回布尔值

    /set 清空/
    st.clear();

5. map<K,V>

  • 底层:红黑树,存pair<K,V>

  • key自动排序,key不允许重复

  • 查找插入删除

  • 迭代器:双向迭代器

  • ✅可以修改it->second不能修改key(it->first只读)

    #include

    /map 生成/
    map<key_type, value_type> name;
    map<int, int> mp;

    /map 迭代器/
    map<int, int>::iterator iter
    mp.begin()
    mp.end()

    #include

    /map 生成/
    map<key_type, value_type> name;
    map<int, int> mp;

    /遍历/
    for (auto p : mp)
    {
    // p.first 是 key
    // p.second 是 value
    cout << p.first << " " << p.second << endl;
    }

    /map 插入/
    mp[2] = 5; //直接添加
    mp.insert(pair<int, int>(2, 5)); //insert一个pair

    /删除/
    mp.erase(iter); //删除迭代器所指的键值对

    /map 容量/
    mp.size()

    /map 查找/
    mp.find(2) //从前往后找,若找到,返回指向该处的迭代器;反之,返回迭代器mp.end()

    /map 某元素个数/
    mp.count(2); //返回key为2的个数(map中只可能是0或者1)

    /map 判空/
    mp.empty() //返回布尔值

    /map 清空/
    mp.clear();

unordered_map<K,V>

无序,无迭代器

7. queue<T> 队列(默认底层deque)

  • 先进先出 FIFO

  • push() pop() front() back()

  • ❌没有迭代器

    #include

    /queue 生成/
    queue q;

    /queue 头尾/
    q.front();
    q.back();

    /queue 插入/
    q.push(2); //在队尾插入一个元素

    /queue 删除/
    q.pop(); //在队首删除一个元素

    /queue 容量/
    q.size();

    /queue 判空/
    q.empty()

8. priority_queue<T>优先队列(堆,默认大根堆,底层vector)

  • 堆,每次取最大元素

  • top()取堆顶;pop()弹出堆顶

  • ❌没有迭代器,不能遍历全部元素

    #include

    /priority_queue 生成/
    priority_queue q; //大根堆
    priority_queue<int, vector, greater> q; //小根堆

    /priority_queue 插入/
    q.push(2); //把一个元素插入堆

    /priority_queue 删除/
    q.pop(); //删除堆顶的元素

    /priority_queue 堆顶/
    q.top(); //返回堆顶元素

    /priority_queue 容量/
    q.size();

    /priority_queue 判空/
    q.empty()

9. stack<T> 栈(默认底层deque)

  • 后进先出 LIFO

  • 接口:push() pop() top() empty() size()

  • 没有迭代器,不能遍历

复制代码
#include <stack>

/*stack 生成*/
stack<int> sk;

/*stack 插入*/
sk.push(2); //把一个元素放入栈 

/*stack 删除*/
sk.pop(); //删除栈顶的元素 

/*stack 栈顶*/
sk.top(); //返回栈顶元素 

/*stack 容量*/
sk.size();

/*stack 判空*/
sk.empty()

算法简介

今天介绍的成员函数,有assign,insert,count,erase,lower_bound,upper_bound

1.assign

用法1:assign(个数,值),表示生成n个相同的元素,覆盖原有的内容。

复制代码
vector<int> v;
v.assign(5, 8);  
// 结果:5个8 → [8,8,8,8,8]
//同样的他能用于其他类型的,比如string类型的话可以是s.assign(4,'x') 表示对s清空并且开一个4个单位的x,结果是"xxxx"

用法2:assign(起始迭代器,结束迭代器) 把另一个容器的区间内容复制过来,覆盖自己

复制代码
vector<int> a = {1,2,3,4};
vector<int> b;
b.assign(a.begin(), a.end());// 把 a 全部复制给 b
b.assign(a.begin(), a.begin()+3);// 只复制前3个

string s1 = "hello";
string s2;
s2.assign(s1.begin(), s1.end());
2:insert

能用容器:vector,string,deque,set,map,(stack,queue不能用)

复制代码
vector<int> v = {1,2,3};
v.insert(v.begin() + 1, 99);// 变成:1,99,2,3

string s = "abc";
s.insert(s.begin()+1, 'x');// 变成 a x b c

set<int> st;
st.insert(5);
st.insert(2);
st.insert(5); // 重复,自动丢掉

map<int, string> mp;
mp.insert({1, "小明"});
mp.insert({2, "小红"});
3.count

**作用:**统计某个值在容器里出现的个数

对集合/映射来说,只能来判断有没有这个元素

哪些容器能用:set,map

vector,deque,string无自带count但是可以用算法

stack,queue完全没有count

复制代码
在set用法
set<int> st;
st.insert(5);
cout << st.count(5);  // 1
cout << st.count(9);  // 0

在map用法
map<string,int> mp;
mp["张三"] = 18;
cout << mp.count("张三"); // 1
cout << mp.count("李四"); // 0

在vector/deque/string用法
#include <algorithm>
vector<int> v = {1,2,2,3,2};
// 统计2出现几次
int cnt = count(v.begin(), v.end(), 2);
cout << cnt; // 3
string s = "aabcc";
int cnt = count(s.begin(), s.end(), 'c');
4:erase
复制代码
哪些容器能用:vector,string,deque,set,map(stack,queue不能用)
1:vector/string/deque用法
vector<int> v = {10,20,30,40};
v.erase(v.begin() + 1);  // 删除第 1 个位置 → 删掉 20

​2:set
set<int> st;
st.insert(5);
st.erase(5); // 直接删掉 5

​3:map
map<int, string> mp;
mp[1] = "小明";
mp.erase(1); // 删掉 key=1
5:lower_bound和upper_bound

其前提是只能用在有序的东西上

适用于:vector(有序),set(本身有序),map(本身有序)

复制代码
假如你找的数是x
lower_bound(起点,终点,x)//找到第一个""大于等于x"的位置
upper_bound(起点,终点,x)//找到第一个"大于x"的位置

举个例子:1,3,5,5,5,7,9找x=5;
lower_bound->指向第一个5
upper_bound->指向7
vector<int> v = {1,3,5,5,5,7,9};
auto it1 = lower_bound(v.begin(), v.end(), 5); 找>=5 的第一个位置
auto it2 = upper_bound(v.begin(), v.end(), 5);找 >5 的第一个位置

在set/map里怎么用呢?
由于他们自带成员函数
auto it = st.lower_bound(x);
auto it = st.upper_bound(x);
相关推荐
沙盘客2 小时前
AFSIM 官方案例库全景与解读方法论
c++·经验分享·后端
_wxd6663 小时前
STL-stack与queue与priority_queue(容器适配器)
c++
zh路西法4 小时前
【玩转VLA具身智能机械臂】(二):MoveIt2 运动规划——架构、配置与 C++ 上手
c++·机械臂·路径规划·vla·planner·moveit2
Yfhonier4 小时前
【素数定理】素数个数的位数
c++·算法·素数
爱和冰阔落5 小时前
【Linux】Ctrl+C 到底做了什么?从键盘、kill 到 alarm,一次讲清信号的产生
linux·运维·c++·安卓
重生之后端学习5 小时前
15. 三数之和[中等]✅
java·数据结构·算法·leetcode·职场和发展
水饺编程5 小时前
第5章,[Win32 章节] :贝塞尔样条曲线(一)
c语言·c++·windows·visual studio
疯狂打码的少年5 小时前
【数据结构】交换类排序:冒泡与快速排序
数据结构·笔记·算法·排序算法
Nil2086 小时前
leetcode 108有序数组转换为二叉搜索树
数据结构·算法·leetcode