C++:STL

news2024/11/15 21:49:45

STL

文章目录

    • STL
      • STL 绪论
      • 迭代器(iterators)
      • 容器(Containers)
        • vector
        • set,multiset
        • map,multimap
        • stack
        • queue
        • deque
        • priority_queue
        • bitset
      • 算法(Algorithms)
        • sort,count,find,lower_bound,upper_bound,binary_search
        • max_element,nth_element
        • reverse, sort, unique, next_permutation
        • vector,merge
      • 练习题目
        • P1449 后缀表达式
        • P1981 [NOIP2013 普及组] 表达式求值
        • P1996 约瑟夫问题
        • P4715 【深基16.例1】淘汰赛
        • P3378 【模板】堆
        • P1808 单词分类
      • 简单汇总

STL 绪论

C++参考手册:https://zh.cppreference.com/

STL(Standard Template Library),即标准模板库,是一个高效的C++程序库,包含了诸多常用的基本数据结构和算法。

STL是惠普实验室开发的一系列软件的统称,其目的是标准化组件,这样就不用重新开发,可以使用现成的组件。
STL是C++的一部分,因此不用安装额外的库文件。
STL是一种泛型编程。面向对象编程关注的是编程的数据方面,而泛型编程关注的是算法。
它们之间的共同点是抽象和创建可重用代码,但它们的理念截然不同。

C++标准模板库的核心包括以下三个组件:
容器/Containers:容器是用来管理某一类对象的集合。C++提供了各种不同类型的容器,比如 deque、list、vector、map 等。
算法/Algorithms:算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。
迭代器/iterators:迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。

算法部分主要由头文件 ,和 组成。
是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。
体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。
中则定义了一些模板类,用以声明函数对象。

在C++标准中,STL被组织为下面的13个头文件:

<algorithm><deque><functional><iterator><vector><list><map><memory.h><numeric><queue><set><stack><utility>

迭代器(iterators)

数组是用一段连续的内存空间来存储相同类型的数据,可以用下标直接进行索引。

迭代器是为了表示容器中元素位置这个概念产生的,是一种检查容器内元素并遍历元素的数据类型。
C++更趋向于使用迭代器而非下标进行操作,因为标准库(STL)为每一种标准容器定义了一种迭代器类型,只有少数容器支持下标操作访问容器元素。

image

注意 end并不指向容器的任何元素,而是指向容器的最后元素的下一位置,称为超出末端迭代器。
如果 vector为空,则 begin返回的迭代器和 end返回的迭代器相同。
一旦定义和初始化,就相当于把该迭代器和容器进行了某种关联,就像把一个指针初始化为指向某一空间地址一样。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10,INF=0x3f3f3f3f;

int main(){
    // freopen("data.in", "r", stdin);
    vector<int> ve;
    for(int i=1; i<10; i++) ve.push_back(i);
    // 迭代器遍历
    vector<int>::iterator it=ve.begin();
    for(; it!=ve.end(); it++) cout<<*it<<" "; cout<<endl;
    // 反向迭代器遍历
    vector<int>::reverse_iterator rit=ve.rbegin();
    for(; rit!=ve.rend(); rit++) cout<<*rit<<" "; cout<<endl;
    // 常变量迭代器
    vector<int>::const_iterator cit=ve.begin();
    for(; cit!=ve.end(); cit++) cout<<*cit<<" "; cout<<endl;
    return 0;
}

容器(Containers)

vector

vector 动态数组,其空间增长速度和发行方有关,目前多为 2 倍。

#include<bits/stdc++.h>
#include<vector>
using namespace std;

vector<int> vec1;        // 默认初始化为空
vector<int> vec2(vec1);  // 使用vec1初始化vec2
vector<int> vec3(10);    // 10个值为0的元素
vector<int> vec4(10,4);  // 10个值为4的元素
vector<string> vec5(10, "hello"); // 10个值为"hello"的元素
vector<int> vec6(vec5.begin(), vec5.end());
int arr[5] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr+5); // 利用数组初始化

int main() {
    int x=111, pos=1, n=10;
    vec.push_back(x);   // 末尾添加数据 x
    vec.pop_back();     // 末尾删除元素
    vec.insert(vec.begin()+pos,x);  // 在第pos个位置前插入 x
    vec.front();        // 首位元素
    vec.back();         // 末位元素
    vec.empty();        // 是否为空
    vec.size();         // 返回元素数
    vec.resize(n);      // 将长度设置为 n
    vec.reserve(n);     // 将空间设置为 n个元素大小
    vec.capacity();     // 返回空间容量,最大能存放元素个数
    vec.clear();        // 清空
    vec.begin();        // 开始指针,指向第一个元素的位置
    vec.end();          // 末尾指针,指向最后一个元素的下一个位置
    vec[1];             // 下标访问,并不会检查是否越界

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

    for(auto u:vec) cout<<u<<" ";
    cout<<endl;
}
#include<iostream>
#include<vector>
using namespace std;
vector<int> ve;

int main(){
    cout<<"大小:"<<ve.size()<<" 容量:"<<ve.capacity()<<endl;
    int n=10;
    for(int i=0; i<n; i++) {
        ve.push_back(i);
        cout<<"大小:"<<ve.size()<<" 容量:"<<ve.capacity()<<endl;
    }
    // 下标遍历
    for(int i=0; i<n; i++) cout<<ve[i]<<" "; cout<<endl;

    ve.reserve(n+5); // 扩容,capacity增加
    cout<<"大小:"<<ve.size()<<" 容量:"<<ve.capacity()<<endl;
    for(auto v : ve)  cout<<v<<" ";  cout<<endl;
    return 0;
}
set,multiset

set:唯一键的集合,按照键排序,可以理解为自带升序排序&去重功能。
set去重, multiset不去重。

#include<bits/stdc++.h>
#include<set>
using namespace std;

int main() {
    int x=111, pos=1, n=10;
    set<int> s;      // 定义一个set集合
    s.insert(x);     // 插入一个元素x
    s.count(x);      // 计算元素x的个数
    s.size();        // 元素的个数
    s.max_size();    // 最大能存元素的数目
    s.begin();       // 第一个元素地址
    s.rbegin();      // 逆向的第一个地址
    s.end();         // 最后一个元素地址
    s.rend();        // 逆向的最后一个地址
    s.empty();       // 是否为空
    s.clear();       // 清空
    s.erase(x);      // 删除成功返回1,否则返回0
    set<int>::iterator it=s.begin(); // 迭代器
    it=s.find(x);    // 返回指向被查找到元素的迭代器,未查找到则为末尾元素
    s.erase(it);     // 按照迭代器删除元素

    for( ; it!=s.end(); it++) cout<<*it<<" "; cout<<endl;
    for(int u:s) cout<<u<<" "; cout<<endl;
    for(auto u:s) cout<<u<<" "; cout<<endl;
}
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
int n=10,x=2;  set<int> s;
int main(){
    for(int i=0; i<n; i++) {
        int x; cin>>x; s.insert(x);
    }
    set<int>::iterator it=s.begin();
    for(; it!=s.end(); it++) cout<<*it<<" "; cout<<endl;
    cout<<count(s.begin(),s.end(),x)<<endl;
    cout<<*find(s.begin(),s.end(),x)<<endl;
    cout<<*lower_bound(s.begin(),s.end(),x)<<endl;
    cout<<*upper_bound(s.begin(),s.end(),x)<<endl;
    s.erase(-1); //删除-1
    a.clear();   //清空
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

int main() {
    set<int> a;
    multiset<int> ma;

    a.insert(1);
    a.insert(2),a.insert(2);
    a.insert(-1),a.insert(-1);
    a.insert(200);
    for(auto u : a) cout<<u<<" "; cout<<endl;

    ma.insert(200);
    ma.insert(a.begin(), a.end());
    for(auto u : ma) cout<<u<<" "; cout<<endl;

    cout<<a.count(200)<<" "<<ma.count(200)<<endl;
    int x = -1;
    if(a.find(x) != a.end()) cout<<"find : "<< *a.find(x)<<endl;
    else cout<<"no find"<<endl;
    x = 200;
    if(ma.find(x) != ma.end()) cout<<"find : "<< *ma.find(x)<<endl;
    else cout<<"no find"<<endl;

    a.erase(-1);
    ma.erase(200);
    for(auto u : a) cout<<u<<" "; cout<<endl;
    for(auto u : ma) cout<<u<<" "; cout<<endl;
    a.clear();
    return 0;
}
map,multimap

map:键值对的集合,按照键排序,键是唯一的,即key-value,按key排序。
map去重,multimap 不去重。

  • 常用函数
map<string,int> mp;             // map<key,value>集合
map<string,int>::iterator it;   // 迭代器
it=mp.find(key);                // 查找key的迭代器
mp.erase(it);                   // 迭代器删除
int val=mp[key];                // 通过key访问value
mp[key]=val;                    // 插入一组映射关系
int flag=mp.erase(key);         // 删除成功返回1,否则返回0
mp.erase(mp.begin(),mp.end());  // 删除区间[begin,end)
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
int n=10,x=2;  map<int,int> t;
int main(){
    for(int i=0; i<n; i++) {
        int x; cin>>x; t.insert(make_pair(x,i));
        //t.insert(pair<int,int>(x,i));
    }
    map<int,int>::iterator it=t.begin();
    for(; it!=t.end(); it++){
        cout<<it->first<<":"<<it->second<<endl;
    }
    t.erase(t.find(x)); //迭代器删除元素
    cout<<"count(x)="<<t.count(x)<<endl;
    t.erase(t.begin(), t.edn()); //清空
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

int main() {
    map<int,string> a;
    multimap<int,string> ma;
    a.insert(map<int,string>::value_type(1,"one"));
    a.insert(make_pair(-1, "minus one"));
    a.insert(pair<int,string>(1000, "one thousand"));
    a[1000000] = "one mullion";
    cout<<"size:"<<a.size()<<endl;
    for(auto v : a) cout<<v.first<<" "<<v.second<<endl;

    ma.insert(multimap<int,string>::value_type(1, "one"));
    ma.insert(make_pair(-1, "minus one"));
    ma.insert(pair<int,string>(1000, "one thousand"));
    ma.insert(pair<int,string>(1000, "one thousand"));
    cout<<"size:"<<ma.size()<<endl;
    for(auto v : ma) cout<<v.first<<" "<<v.second<<endl;

    multimap<int,string>::const_iterator p=ma.find(1);
    if(p != ma.end())
        cout<<"find : "<<p->first<<" "<<p->second<<endl;
    else cout<<"no find"<<endl;

    cout<<a[1]<<endl;
//    cout<<a[2]<<endl;  // 这样查询是不对的,a[] 重载了 [],进行了新建
    map<int,string>::iterator temp=a.find(2);
    if(temp != a.end())
        cout<<"find : "<<temp->first<<" "<<temp->second<<endl;
    else cout<<"no find"<<endl;

    ma.erase(-1);
    ma.erase(ma.lower_bound(100), ma.upper_bound(100));
    return 0;
}

set,multiset,map,multimap都是基于平衡二叉搜索树(红黑树)的,有序
unordered_set,unordered_map是基于Hash的,无序。

unordered_set<string> us;
unordered_map<string,int> um;

stack和queue 在上文已经讲过,文章:https://www.cnblogs.com/hellohebin/p/15677386.html

stack

栈:具有后进先出(Last In First Out)特性的线性表

#include<stack> // 栈的头文件

stack<int> sta; // 栈的定义
sta.push(x);    // 入栈
sta.pop();      // 出栈
sta.top();      // 栈顶
sta.empty();    // 栈是否为空
sta.size();     // 栈内元素个数
queue

队列:具有先进先出(First In First Out)特性的线性表

#include<queue> // 队列的头文件

queue<int> que; // 队列的定义
que.push(x);    // 入队
que.pop();      // 出队
que.front();    // 队首
que.back();     // 队尾
que.empty();    // 队列是否为空
que.size();     // 队内元素个数
deque

双向队列:队首和队尾均可进行插入删除的线性表

#include<iostream>
#include<deque>
using namespace std;
int n=10;  deque<int> dque;//定义格式
int main(){
    for(int i=0; i<n; i++) {
        int x; cin>>x;
        dque.push_front(x); //队首添加
    }
    dque.push_back(10); //队尾添加
    dque.pop_back();    //队尾出队
    cout<<"队首元素:"<<dque.front()<<endl;
    cout<<"队尾元素:"<<dque.back()<<endl;
    while(!dque.empty()){
        cout<<dque.front()<<" ";
        dque.pop_front();//队首出队
    } cout<<endl;
    return 0;
}
priority_queue

在优先队列中,元素被赋予优先级。
当访问元素时,具有最高优先级的元素最先删除。
优先队列具有最高级先出 (first in, largest out)的行为特征。
通常采用堆数据结构来实现。

#include<iostream>
#include<queue>
using namespace std;
int n=10,a[10]={1,2,3,4,5,6,7,8,9,0};
priority_queue<int> q1;  //默认大顶堆
priority_queue<int, vector<int>, greater<int> > q2;//小顶堆
priority_queue<int, vector<int>, less<int> > q3;   //大顶堆
int main() {
    for(int i=0; i<n; i++) {
        q1.push(a[i]); q2.push(a[i]); q3.push(a[i]);
    }
    while(!q1.empty()) {
        cout<<q1.top()<<" "; q1.pop();
    }cout<<endl;// 9 8 7 6 5 4 3 2 1 0

    while(!q2.empty()) {
        cout<<q2.top()<<" "; q2.pop();
    }cout<<endl;// 0 1 2 3 4 5 6 7 8 9

    while(!q3.empty()) {
         cout<<q3.top()<<" "; q3.pop();
    }cout<<endl;// 9 8 7 6 5 4 3 2 1 0
    return 0;
}
make_heap(ve.begin(), ve.end());  //建立一个堆
push_heap(ve.begin(), ve.end());  //添加一个元素在末尾,重新调整堆序
pop_heap(ve.begin(), ve.end());   //把堆顶元素取出来,放到末尾
sort_heap(ve.begin(), ve.end());  //在堆上进行升序排序

#include<bits/stdc++.h>
using namespace std;

int main() {
    vector<int> ve;
    for(int i=3; i<=7; i++) ve.push_back(i);
    for(int i=5; i<=9; i++) ve.push_back(i);
    for(int i=1; i<=4; i++) ve.push_back(i);
    for(auto u : ve) cout<<u<<" "; cout<<endl;

    make_heap(ve.begin(), ve.end());
    for(auto u : ve) cout<<u<<" "; cout<<endl;

    pop_heap(ve.begin(), ve.end()); ve.pop_back();
    for(auto u : ve) cout<<u<<" "; cout<<endl;

    ve.push_back(17); push_heap(ve.begin(), ve.end());
    for(auto u : ve) cout<<u<<" "; cout<<endl;

    sort_heap(ve.begin(), ve.end());
    for(auto u : ve) cout<<u<<" "; cout<<endl;
    return 0;
}
bitset
#include<bits/stdc++.h>
using namespace std;

int main() {
    bitset<16> s1, s2;
    bitset<16> res = s1^s2; // 支持位运算
    cout<<s1.count()<<endl; // 返回 1 的个数
    cout<<s1.any()<<endl;   // 若所有位都为0,返回false,否则返回 true
    cout<<s1.none()<<endl;  // 若所有位都为0,返回false,否则返回 true

    s1[15]=1;
    s1.set();   // 所有位赋值为 1
    s1.reset(); // 所有位赋值为 0
    s1.flip();  // 所有位取反
    s1 = 15;    // 通过 10进制赋值
    cout<<s1<<endl;
    return 0;
}

算法(Algorithms)

sort,count,find,lower_bound,upper_bound,binary_search
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e4;
int a[N], n=10, x=2;
int main(){
    for(int i=0; i<n; i++) cin>>a[i];
    sort(a, a+n); //升序排序
    for(int i=0; i<n; i++) cout<<a[i]<<" "; cout<<endl;
    cout<<count(a, a+n, x)<<endl;  //x出现的次数
    cout<<*find(a, a+n, x)<<endl;  //x首次出现,未出现返回0
    cout<<*lower_bound(a, a+n, x)<<endl;  //不小于x的第一个数
    cout<<*upper_bound(a, a+n, x)<<endl;  //大于x的第一个数
    cout<<binary_search(a, a+n, x)<<endl; //x是否存在
    return 0;
}
max_element,nth_element
#include<bits/stdc++.h>
using namespace std;

bool absless(int a,int b){
    return abs(a) < abs(b);
}
int main() {
    int a[10]={-11,2,3,4,5,6,7,8,9,0};
    int maxv = *max_element(a, a+10);
    int minv = *min_element(a, a+10);
    int absmaxv = *max_element(a, a+10, absless);
    int absminv = *min_element(a, a+10, absless);
    cout<<"最大值:"<<maxv<<" 最小值:"<<minv<<endl;
    cout<<"绝对值最大值:"<<absmaxv<<" 绝对值最小值:"<<absminv<<endl;
    int n=10, k=3;
    nth_element(a, a+k, a+n);
    cout<<a[k]<<endl; // 第 k 小,第 n-k+1 大
    return 0;
}
reverse, sort, unique, next_permutation
#include<bits/stdc++.h>
using namespace std;
vector<int> ve = {1,2,5,3,4,5,5};
int main() {
    reverse(ve.begin(),ve.end());
    for(auto u : ve) cout<<u<<" "; cout<<endl;
    // unique 去除相邻的重复元素,返回去重后最后一个元素的地址
    sort(ve.begin(),ve.end()); // unique使用前需要保证有序
    int size = unique(ve.begin(), ve.end())-ve.begin();
    cout<<"size : "<<size<<endl;
    for(auto u : ve) cout<<u<<" "; cout<<endl;

    sort(ve.begin(), ve.end());
    do {
//        for(auto u: ve) cout<<u<<" "; cout<<endl;
    } while(next_permutation(ve.begin(),ve.end()));//下一个排列

    for(auto u: ve) cout<<u<<" "; cout<<endl;
    // 不小于 x的元素位置
    cout<<lower_bound(ve.begin(),ve.end(),3)-ve.begin()<<endl;

    // 大于 x的元素位置
    cout<<upper_bound(ve.begin(),ve.end(),3)-ve.begin()<<endl;
    return 0;
}
vector,merge
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> ve;

int main(){
    int n=10,x=0;
    for(int i=0; i<n; i++) ve.push_back(i);
    // 满足条件的元素数.
    cout<<count(ve.begin(), ve.end(), x)<<endl;

    // 指向首个满足条件的迭代器,或若找不到这种元素则为 end.
    cout<<*find(ve.begin(), ve.end(), x)<<endl;

    // 指向首个不小于 value 的元素的迭代器,或若找不到这种元素则为 end.
    cout<<*lower_bound(ve.begin(), ve.end(), x)<<endl;

    // 指向首个大于 value 的元素的迭代器,或若找不到这种元素则为 end.
    cout<<*upper_bound(ve.begin(), ve.end(), x)<<endl;

    sort(ve.begin(), ve.end());// 用默认的 operator< 排序

    // 若找到等于 value 的元素则为 true ,否则为 false.
    cout<<binary_search(ve.begin(), ve.end(), x)<<endl;

    vector<int> ve2(5),ve3;// 归并两个已排序的范围
    merge(ve.begin(),ve.end(),ve2.begin(),ve2.end(),back_inserter(ve3));
    for(auto u : ve3) cout<<u<<" "; cout<<endl;
    return 0;
}

练习题目

P1449 后缀表达式

所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:3*(5–2)+7 对应的后缀表达式为:3.5.2.-*7.+@。
'@‘为表达式的结束符号,’.'为操作数的结束符号。字符串长度在1000内。

输入格式:后缀表达式
输出格式:表达式的值

输入样例:3.5.2.-*7.+@
输出样例:16
#include<bits/stdc++.h>
using namespace std;
stack<int> sta;  int a,b,c;  char ch;
int main(){
    while((ch=getchar())!='@'){
        if(ch<='9' && ch>='0'){
            a=a*10+ch-'0';
        }else if(ch=='.'){
            sta.push(a);  a=0;
        }else {
            a=sta.top(),sta.pop();
            b=sta.top(),sta.pop();
            if(ch=='+'){ c = b+a; }
            else if(ch=='-'){ c = b-a; }
            else if(ch=='*'){ c = b*a; }
            else if(ch=='/'){ c = b/a; }
            sta.push(c);  a=b=0;
        }
    }
    cout<<c<<endl;  return 0;
}
P1981 [NOIP2013 普及组] 表达式求值

给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值。
输入一行需要计算的表达式,表达式中只包含数字、加法运算符‘+’和乘法运算符‘×’,且没有括号,所有参与运算的数字均为 0 到 pow(2,31)-1之间的整数。输入数据保证这一行只有 0-9、+、× 这12种字符。
输出一个整数,表示这个表达式的值,当答案长度多于4位时,请只输出最后4位,前导0不输出。

输入样例:1+1*3+4
输出样例:8
#include<bits/stdc++.h>
using namespace std;
stack<long long> sta;
int a,b,ans=0, mod=10000;  char ch;
int main() {
    cin>>a;  a %= mod;  sta.push(a);
    while(cin>>ch>>b) {
        b %= mod;
        if(ch=='*') {
            a = sta.top();  sta.pop();
            sta.push(a*b%mod);
        } else if(ch=='+') { sta.push(b); }
    }
    while(!sta.empty()) {
        ans += sta.top(), sta.pop();
        ans %= mod;
    }
    cout<<ans%mod;    return 0;
}
P1996 约瑟夫问题

n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 1 开始报数,数到 m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。

输入格式:输入两个整数 n,m(1≤m,n≤100)。
输出格式:输出一行 n 个整数,按顺序输出每个出圈人的编号。

输入样例:10 3
输出样例:3 6 9 2 7 1 8 5 10 4
#include<bits/stdc++.h>
using namespace std;
queue<int> que;
int main(){
    int n,m,cnt=1; cin>>n>>m;
    for(int i=1; i<=n; i++) que.push(i);
    while(!que.empty()){
        if(cnt<m){
            que.push(que.front());
            que.pop();  cnt++;
        }else if(cnt==m){
            cout<<que.front()<<" ";
            que.pop();  cnt=1;
        }
    } return 0;
}
P4715 【深基16.例1】淘汰赛

有 2^n(n≤7) 个国家参加世界杯决赛圈且进入淘汰赛环节。
我经知道各个国家的能力值,且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。
1 号国家和 2 号国家踢一场比赛,胜者晋级。3 号国家和 4 号国家也踢一场,胜者晋级……晋级后的国家用相同的方法继续完成赛程,直到决出冠军。
给出各个国家的能力值,请问亚军是哪个国家?

输入样例输出样例
3
4 2 3 1 10 5 9 7
1
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
int main() {
    int n; cin>>n; n = pow(2, n); // n=1<<n;
    queue<pair<int, int> > que;
    for(int i=1; i<=n; i++) {
        int a; cin>>a; que.push(make_pair(i, a));
    }
    while( que.size() > 2 ){
        pair<int, int> x,y;
        x = que.front(); que.pop();
        y = que.front(); que.pop();
        if(x.second > y.second) que.push(x);
        else que.push(y);
    }
    pair<int, int> x,y;
    x = que.front(); que.pop();
    y = que.front(); que.pop();
    if(x.second > y.second) cout<<y.first;
    else cout<<x.first;
    return 0;
}
P3378 【模板】堆

给定一个数列,初始为空,请支持下面三种操作:

  1. 给定一个整数 x,请将 x 加入到数列中。
  2. 输出数列中最小的数。
  3. 删除数列中最小的数(如果有多个数最小,只删除 1 个)。

输入格式:第一行是一个整数,表示操作的次数 n。
接下来 n 行,每行表示一次操作。每行首先有一个整数 op 表示操作类型。
若 op=1,则后面有一个整数 x,表示要将 x 加入数列。
若 op=2,则表示要求输出数列中的最小数。
若 op=3,则表示删除数列中的最小数。如果有多个数最小,只删除 1 个。

输出格式:对于每个操作 2,输出一行一个整数表示答案。

输入样例输出样例
5
1 2
1 5
2
3
2
2
5
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> > pq;
//priority_queue<int, vector<int>, less<int> > pq;
int main(){
    int n;  cin>>n;
    for(int i=1; i<=n; i++){
        int f; cin>>f;
        if(f==1){
            int x;  cin>>x;  pq.push(x);
        }else if(f==2){
            cout<<pq.top()<<endl;
        }else if(f==3){
            pq.pop();
        }
    } return 0;
}
P1808 单词分类

【题目描述】
两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等。
例如 “AABAC”,它和 “CBAAA” 就可以归为一类,而和 “AAABB” 就不是一类。
现在Oliver有N个单词,所有单词均由大写字母组成,每个单词的长度不超过100。
你要告诉Oliver这些单词会被分成几类。

【输入格式】输入文件的第一行为单词个数N,以下N行每行为一个单词。

【输出格式】输出文件仅包含一个数,表示这N个单词分成的类数

输入样例输出样例
3
AABAC
CBAAA
AAABB
2
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+1;
char s[N][101];
int main(){
    int n; cin>>n;
    for(int i=1; i<=n; i++){
        scanf("%s", s[i]);
        sort(s[i], s[i]+strlen(s[i]));
    }
    map<string,int> m;
    for(int i=1; i<=n; i++){
        m.insert(pair<string,int>(s[i],1));
    }
    printf("%d", m.size());
    return 0;
}

STL的内容其实还有很多,但是我们目前无法做到面面俱到,只能先学习其中的精华部分,并将之用到自己的程序中。很多人都会说依据话,就是“慎用STL”,主要原因是STL慢,空间容易出问题,那么开O2优化后,这些问题其实能有很大的改善,与自己手写几乎相差无几。当然最后如何抉择,还是要看个人习惯。

本文到此就暂时告一段落,之后仍然会不断更新,但是不会变的冗余,毕竟是“汲取精华”。如果你觉得不错或者有什么建议,认为文中需要补充的,欢迎留言。

简单汇总

C++ STL简介
vector, 变长数组,倍增的思想
    size()  返回元素个数
    empty()  返回是否为空
    clear()  清空
    front()/back()
    push_back()/pop_back()
    begin()/end()
    []
    支持比较运算,按字典序

pair<int, int>
    first, 第一个元素
    second, 第二个元素
    支持比较运算,以first为第一关键字,以second为第二关键字(字典序)

string,字符串
    size()/length()  返回字符串长度
    empty()
    clear()
    substr(起始下标,(子串长度))  返回子串
    c_str()  返回字符串所在字符数组的起始地址

queue, 队列
    size()
    empty()
    push()  向队尾插入一个元素
    front()  返回队头元素
    back()  返回队尾元素
    pop()  弹出队头元素

priority_queue, 优先队列,默认是大根堆
    size()
    empty()
    push()  插入一个元素
    top()  返回堆顶元素
    pop()  弹出堆顶元素
    定义成小根堆的方式:priority_queue<int, vector<int>, greater<int>> q;

stack,size()
    empty()
    push()  向栈顶插入一个元素
    top()  返回栈顶元素
    pop()  弹出栈顶元素

deque, 双端队列
    size()
    empty()
    clear()
    front()/back()
    push_back()/pop_back()
    push_front()/pop_front()
    begin()/end()
    []

set, map, multiset, multimap, 基于平衡二叉树(红黑树),动态维护有序序列
    size()
    empty()
    clear()
    begin()/end()
    ++, -- 返回前驱和后继,时间复杂度 O(logn)

    set/multiset
        insert()  插入一个数
        find()  查找一个数
        count()  返回某一个数的个数
        erase()
            (1) 输入是一个数x,删除所有x   O(k + logn)
            (2) 输入一个迭代器,删除这个迭代器
        lower_bound()/upper_bound()
            lower_bound(x)  返回大于等于x的最小的数的迭代器
            upper_bound(x)  返回大于x的最小的数的迭代器
    map/multimap
        insert()  插入的数是一个pair
        erase()  输入的参数是pair或者迭代器
        find()
        []  注意multimap不支持此操作。 时间复杂度是 O(logn)
        lower_bound()/upper_bound()

unordered_set, unordered_map, unordered_multiset, unordered_multimap, 哈希表
    和上面类似,增删改查的时间复杂度是 O(1)
    不支持 lower_bound()/upper_bound(), 迭代器的++--

bitset, 圧位
    bitset<10000> s;
    ~, &, |, ^
    >>, <<
    ==, !=
    []
    count()  返回有多少个1

    any()  判断是否至少有一个1
    none()  判断是否全为0

    set()  把所有位置成1
    set(k, v)  将第k位变成v
    reset()  把所有位变成0
    flip()  等价于~
    flip(k) 把第k位取反

参考资料:
https://blog.csdn.net/u010183728/article/details/81913729
https://blog.csdn.net/qq_50285142/article/details/114026148
https://blog.csdn.net/weixin_43679037/article/details/118833261

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1699127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序基础 -- 小程序UI组件(5)

小程序UI组件 1.小程序UI组件概述 开发文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/view/component.html 什么是组件&#xff1a; 组件是视图层的基本组成单元。 组件自带一些功能与微信风格一致的样式。 一个组件通常包括 开始标签 和 结…

安全分析[1]之网络协议脆弱性分析

文章目录 威胁网络安全的主要因素计算机网络概述网络体系结构 网络体系结构脆弱性分组交换认证与可追踪性尽力而为匿名与隐私对全球网络基础实施的依赖无尺度网络互联网的级联特性中间盒子 典型网络协议脆弱性IP协议安全性分析IPSec&#xff08;IP Security)IPv6问题 ICMP协议安…

python基于深度学习的聊天机器人设计

python基于深度学习的聊天机器人设计 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 登录注册功能 用户在没有登录自己的用户名之前只能浏览本网站的首页&#xff0c;想要使用其他功能都…

GitHub怎么修改个人资料名称name和用户名username

文档 GitHub•GitHub文档•Get started•帐户和个人资料•配置文件•自定义个人资料•个性化设置https://docs.github.com/zh/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile GitHub•GitHub文档•G…

Scala的简单认识

Scala编程基础 小白的Scala学习笔记 2024/5/21 上午某一时刻 文章目录 Scala编程基础spark是用Scala开发出来的Scala的优点 打开idea 搜索scala&#xff0c;安装 如果不小心点了取消&#xff0c;或者没有上图的提示&#xff0c;就在依赖里面添加 spark是用Scala开发出来的 类比…

Linux环境下TensorFlow安装教程

TensorFlow是学习深度学习时常用的Python神经网络框 下面以Mask R-CNN 的环境配置为例&#xff1a; 首先进入官网&#xff1a;www.tensorflow.org TensorFlow安装的总界面&#xff1a; 新建anaconda虚拟环境&#xff1a; conda create -n envtf2 python3.8 &#xff08;Pyth…

K8S认证|CKA题库+答案| 15. 备份还原Etcd

目录 15、 备份还原Etcd CKA v1.29.0模拟系统 下载试用 题目&#xff1a; 开始操作: 1&#xff09;、切换集群 2&#xff09;、登录master并提权 3&#xff09;、备份Etcd现有数据 4&#xff09;、验证备份数据快照 5&#xff09;、查看节点和Pod状态 6&#xff0…

Cadence OrCAD学习笔记(3)capture使用技巧_1

本期介绍capture的一些使用技巧。资料来源于小破站up主硬小二 1、导出像Visio规格的图纸 2、全局修改元件属性 然后保存、关闭即可。 3、导出BOM 4、导出网表 5、元件自动编号 6、capture软件和allegro关联 7、新建原理图symbol 以上为添加封装库的路径 如果要创建多部分的sy…

反弹shell详细易懂讲解,看这一篇就够了

文章目录 反弹shell详细易懂讲解&#xff0c;看这一篇就够了一: 基础shell知识什么是shell&#xff0c;bash与shell的区别?通俗解释类型功能常见命令 二: 什么是反弹shell三: 反弹shell类型bash反弹shellNetcat 一句话反弹curl反弹shell正确姿势 wget方式反弹awk反弹 Shellsoc…

线性模型--普通最小二乘法

线性模型 一、模型介绍二、用于回归的线性模型2.1 线性回归&#xff08;普通最小二乘法&#xff09; 一、模型介绍 线性模型是在实践中广泛使用的一类模型&#xff0c;该模型利用输入特征的线性函数进行预测。 二、用于回归的线性模型 以下代码可以在一维wave数据集上学习参…

AWS CloudWatch日志组中关于中文关键字的查询

问题 在AWS CloudWatch日志组中&#xff0c;想要查询出包含中文关键字的错误日志&#xff0c;结果&#xff0c;AWS说语法错误。 最开始&#xff0c;使用如下查询&#xff0c;查询可能的错误日志&#xff1a; 查询语句&#xff0c;如下&#xff1a; {($.log %ERROR%) }具体效…

神器EasyRecovery2024中文电脑版下载!让数据恢复不再难

在数字化时代&#xff0c;数据就是我们的财富。无论是重要的工作报告&#xff0c;还是那些珍贵的生活瞬间照片&#xff0c;或是我们与朋友间的聊天记录&#xff0c;都储存在我们的电脑或手机中。然而&#xff0c;有时候&#xff0c;意外总是突如其来&#xff0c;电脑突然崩溃&a…

中国区 AWS 控制台集成 ADFS 登录

前言 本文将使用一台 Windows Server 2019 服务器实现自建 AD ADFS 环境集成到中国区 AWS 控制台进行单点登录. 参考文档: https://aws.amazon.com/cn/blogs/china/adfs-bjs/ 配置 AD 生产环境建议先给本地连接设置静态 IP 地址, 不设置也没事儿, 后面配置功能的时候会有 W…

HTML与CSS的学习

什么是HTML,CSS&#xff1f; HTML(HyperText Markup Language):超文本标记语言。 超文本:超越了文本的限制&#xff0c;比普通文本更强大。除了文字信息&#xff0c;还可以定义图片、音频、视频等 标记语言:由标签构成的语言 >HTML标签都是预定义好的。例如:使用<a>…

python深入解析字符串操作的八大神技

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、字符串的长度与切片 示例代码 二、去除多余的空格 示例代码 三、字符串的开头与包含…

VXLAN小结

1.VXLAN:(组件虚拟网络的架构核心)虚拟扩展本地局域网&#xff0c;通过隧道的形式&#xff0c;将物理上有隔离的资源&#xff0c;在逻辑上连通起来&#xff0c;使其二层互通。 a.物理网络:指的是构成 VXLAN 连接的基础 IP 网络 b.逻辑网络:指的是通过 VXLAN 构建的虚拟网络 C.N…

【Linux杂货铺】进程通信

目录 &#x1f308; 前言&#x1f308; &#x1f4c1; 通信概念 &#x1f4c1; 通信发展阶段 &#x1f4c1; 通信方式 &#x1f4c1; 管道&#xff08;匿名管道&#xff09; &#x1f4c2; 接口 ​编辑&#x1f4c2; 使用fork来共享通道 &#x1f4c2; 管道读写规则 &…

DEM、DSM和DTM之间的区别及5米高程数据获取

在日常的学习工作中我们经常会遇到DEM、DSM和DTM等术语&#xff0c;它们的含义类似&#xff0c;甚至相互替换。那么它们之间有什么区别&#xff1f;这里我们对这些术语进行介绍。 DEM&#xff08;数字高程模型&#xff0c;Digital Elevation Model&#xff09;&#xff1a; 定义…

24法考证件照要求|不合格原因汇总!

6月法考报名&#xff0c;大家一定要提前熟悉下电子证件照片要求‼️ ⚠️证件照注意事项 ▪️不得上传全身照、风景照、生活照、背带(吊带)衫照、艺术照、侧面照、不规则手机照等。 ▪️本人近三个月内彩色(红、蓝、白底色均可)正面免冠电子证件照片&#xff0c;照片必须清晰完…

<商务世界>《75 微课堂<茶叶(1)-质量分级>》

1 中国茶叶分级 中国的10级标准是按照茶叶的外观、香气、滋味、汤色、叶底五个方面进行评分&#xff0c;分别用10分制进行评分&#xff0c;总分为50分&#xff0c;得分越高&#xff0c;茶叶的品质就越高。具体的分数和等级如下表所示&#xff1a; 2 每级的特点 茶叶的质量等级…