蓝桥杯算法基础(38)c++ STL

时间:2024-04-07 13:37:58

哈希表的常用函数


#include<iostream>
#include<unordered_map>
#include<string>

int main(){
    //创建一个unordered_map实例
    std::unordered_map<std::string,int>hash_table;
    
    //插入数据
    hash_table["one"]=1;
    
    int key="one";
    if(hash_table.find(key)!=hash_table.end()){//当find没有找到对应值时,会返回一个end 
        std::cout<<"找到键为"<<key<<"的元素,值为"<<hash_table[key]<<std::endl; 
    
    }
    
        //遍历哈希表
    for(const auto& pair:hash_table){
        
        std::cout<<"键:"<<pair.first<<"值为"<<pair.second<<std::endl;
         
    }
    
    //删除元素
    hash_table.erase("one");
    
    return 0; 

 
 
   

vector几种删除元素的方法

vector是一个非常灵活且功能强大的序列容器
    :
    1.使用erase成员函数删除单个元素
    erase函数可以接受一个迭代器参数,指向要删除的元素。调用erase后,
    它会移除指定位置的元素,并返回下一个元素的迭代器
    
    vector<int>v={1,2,3,4,5};
    auto it=find(v.begin(),v.end(),3);
    if(it!=v.end()){
        v.erase(it);//删除元素3 
    }
    
    2.使用erase成员函数删除指定范围的元素
    erase函数可以接受两个迭代器作为参数,删除一个范围内的元素。
    这两个迭代器应该形成一个有效的区间,表示要删除的元素范围
    
    vector<int> v={1,2,3,4,5,6};
    v.erase(v.begin()+2,v.begin()+4);//删除元素3和4
    
    3.使用clear成员函数删除所有元素
    vector容量保持不变
    v.clear();
    
    4.使用swap和析构函数删除元素
    如果你想删除一个vector中的特定元素,但又不想改变其它元素的顺序,
    可以使用swap函数将该元素vector的最后一个元素交换,然后删除最后一个元素
    
    vector<int>v={1,2,3,4,5};
    swap(v[2],v.back());//将元素3与最后一个元素5交换 
    v.pop_back(); //删除原最后一个元素,即原来的3
    
    5.使用remove和erase成员函数删除满足特定条件的元素
    remove函数可以将满足特定条件的元素移动到vector末尾,并返回一个指向新逻辑末尾的迭代器,
    然后,你可以使用erase函数删除这些元素
    vector<int>v={1,2,3,4,5,3};
    auto newEnd=remove(v.begin(),v.end(),3);//将所有元素3移动到末尾
    v.erase(newEnd,v.end());//删除所有元素3 
     
    使用at()函数安全的访问元素 
    v.erase(v.begin() + indexToDelete);//v.begin()为迭代器起点,indexToDelete为要删除元素的下标 
     
     

 STL 


//快速排序 
//sort(arr.begin(),arr.end());

//向量vector
//vector<类型>arr(长度,[初值]) 


#include<bits/stdc++.h>
using namespace std;
int main(){
    
    
    vector<int>arr;//一维,长度是可变的
     
    vector<vector<int> >dp(5,vector<int> (6,10));//二维数组,5行6列,初值为10
    
    vector<vector<vector<int> > >dp2(5,vector<vector<int> >(6,vector<int>(4)));//三维 
    int mat[5][6][4]; //二者等价 
    
    arr.push_back(1);//在后面添加一个元素 
    
    /*for(auto &e : arr){//arr给的是地址,因此需要&,auto自动改变相应类型 
        cout<<e<<endl;
    } */
    
    
    arr.pop_back();//删除后面一个元素
    
    arr.clear();//清空vector中的所有元素
    
    if(arr.empty()){//判断是否为空 
    cout<<"为空"; 
    }
    
    arr.resize(5,3);//重新设置vector的长度,和初值(默认值),(长度,初值)
    
    //vector从在于对空间不会爆栈 
    
    //能提前声名长度,应直接声明长度,节省时间
    
    arr.size();//得到vector的长度 
    //size()返回的类型是size_t,size_t的大小与编译器有关 
     
         
    return 0;


stack栈 

#include<bits/stdc++.h>
using namespace std;
int main(){
    
    stack<double>stk;
    stk.push(1.0);//入栈 
    stk.push(2.0);
    cout<<stk.top()<<endl;//top()输出栈顶元素 
    stk.pop();//出栈 
    cout<<stk.top()<<endl; 
     
    
    
    //stack与vector很相似,可以将vector当作栈使用 
    vector<double> vec;
    vec.push_back(1.0);
    vec.push_back(2.0);
    cout<<vec.back()<<endl;
    vec.pop_back();
     
         
    return 0;


queue队列 

#include<bits/stdc++.h>
using namespace std;
int main(){
    
     queue<int> que;
     que.push(1)//入队;
     que.push(2);
     cout<<que.front()<<endl;//队首 
     que.pop(); //出队 
     cout<<que.back()<<endl;//队尾 
    cout<<que.size()<<endl;//队长
    cout<<que.empty()<<endl;//是否为空
    
         
    return 0;

 
 
//优先队列priority_queue 
//二叉堆来实现
 //每次从队列中取出大小最大/最小的元素
 //只能访问堆顶 
#include<bits/stdc++.h>
using namespace std;
int main(){
    
    priority_queue<int> pque;
    pque.push(1);//入堆 
    pque.push(2);
    cout<<pque.top()<<endl;//输出堆顶 
    pque.pop();//出堆 
             
    priority_queue<int,vector<int>,greater<int>>pque;//小顶堆如果需要long long就把int该为long long
      
    
    return 0;
}

 集合set



//确定性,互异性,无序性 
//set有确定性,互异性 
//multiset有确定性
//unordered_set有确定性,互异性,无序性
#include<bits/stdc++.h>
using namespace std;
int main(){
    
    set<int> st;
    st.insert(1);//插入元素 
    st.insert(1);//set含有互异性,不能存入两个1 
    st.insert(2);
    st.erase(2);//删除元素
    
    if(st.find(1)!=st.end()){//如果没找到,find()会等于end() 
        cout<<"yes"<<endl;
    }
     
    cout<<st.size()<<endl;//查大小     
    cout<<st.empty()<<endl;//判空
    
    
    
    for(auto &e:st){
        cout<<e<<endl;
    }
    
    //可以使用迭代器来进行遍历
    for(set<int>::iterator it=st.begin();it!=st.end();it++){//迭代器与地址相似,不过移动的是一个类型的长度 
        cout<<*it<<endl;
    }
    
     
         
    return 0;

  
  
  
//bool vis[100]如果出现了vis就记为true   
//当数组大小【-10^18 ~ 10^18】,元素数量10^6,vis数组无法实现,通过set可以实现
 set<int> st;
 
 st.insert(1); 
 st.insert(2);
 
 if(st.count(1)){//如果set里有这个元素count()返回true 
     cout<<"yes"<<endl;
 }
 //set元素只读 
 
 

映射map



//互异性,无序性
 //map含有互异性
 //multimap什么都不含
 //unordered_map含有互异性,无序性
 
#include<bits/stdc++.h>
using namespace std;
int main(){
    
    map<int,int> mp;
    mp[2]=1;//赋值key,vlaue 
    cout<<mp[2]<<endl;//输出value    
     
    if(mp.find(2)!=end()){//是否找到元素key为2的映射 
        cout<<"yes"<<endl;
    }     
    
    mp.erase(2);//消除key为2的映射 
    cout<<mp.count(2)<<endl;//key为2的映射含有几个 
    
    //clear(),size(),empty()
    
    for(map<int>::iterator it=map.begin();it!=mp.end();it++){
        cout<<it->first<<' '<<it->second<<endl;
    } 
    
    for(auto &pr:mp){
        cout<<pr.first<<' '<<pr.second<<endl;
    }
    
    
    
    
    //记录每个单词的数量 
    map<string,int>mp;
    vector<string> word;
    word.push_back("awa");
    word.push_back("awa");
    word.push_back("awa");
    word.push_back("awa");
    
    for(int i=0;i<word.sieze();i++){
        mp[word[i]]++;
    }
    
    for(auto &pr:mp){
        cout<<pr->first<<" "<<pr->second<<endl;
    }
    
    
    //[]访问一个不存在的键的时候,会默认创建这个键,并赋初值为0
     
     
    return 0;
    
    
    

  
  
  

字符串string


 
   
#include<bits/stdc++.h>
using namespace std;
int main(){
    
    string s;
    char buf[100];
    scanf("%s",&buf);//c输入字符串,不需要&,但也不错 
    
    s=buf;
    printf("%s",s.c_str()); //c语言输出 
    cout<<buf;//c++输出 
    
    
    string b(100,'0');
     b="awa";
     cout<<b<<endl;
     
    
    b+='a';//字符串拼接 
    cout<<a+b<<endl;
     
     
    cout<<b.substr(1)<<endl;//从下标为1到末尾的子串
    
    if(b.find("312"!=string::npos)){//如果找不到子串,就会返回npos这个值 
        cout<<"yes"<<endl;
        
    }
    
    int x=stoi(b);//字符串转为整形 
    long long x=stoll(b);
    float x=stof(b);
    double x=stod(b);
    long double stold(b);
    
    
    string b=to_string(x);
    
     
    return 0;
    
    
    

  
 //substr(起点下标,子串长度);
 //find()使用暴力实现的 
 
 
 

二元组pair

#include<bits/stdc++>

using namespace std;

int main(){
    pair<int,int> p1=make_pair(1,2);
    pair<char,int> p2={'a',2};
    
    pair<pair<int,char>,char> p3;
    
    
}

 迭代器iterator


//迭代器
for(vector<int>::iterator it=a.begin();it!=a.end();++it){
    cout<<*it<<endl;
} //正向输出 

for(vector<int>::iterator it=a.rbegin();it!=a.rend();++it){
    cout<<*it<<endl;
}//反向输出 


begin()//头迭代器
end()//尾迭代器
rbegin()//反向头迭代器
rend()//反向尾迭代器
迭代器+整形,迭代器向后移动
迭代器-整形,迭代器向前移动
迭代器++,将迭代器向后移动1位
迭代器--,将迭代器向前移动一位
迭代器-迭代器,两个迭代器的距离
prev(it),it的前一个迭代器
next(it),it的后一个迭代器


.end(),.rend()指向的位置是无意义的值,是不可访问的,如a[10]数组的下标位10的元素

迭代器有正向,反向,双向,每个容器的迭代器支持的运算符也可能不同

vector<int>a{1,2,3,4};
for(auto it=a.begin();it!=a.end();it++){
    if(*it==2||*it==3){
        a.erase(it);
    }
}//最后3没删掉,因为当删掉2时迭代器自动就变为了3的位置,然后再it++就跳过去了
 

for(auto it=a.begin();it!=a.end();it++){
        if(*it==4){
            a.erase(it);
        }
    
} //但删除4后,迭代器变为end(),it++后就越界了

一些常用算法和数学函数


swap(a,b);//交换a和b的值 
sort(arr.begin(),arr.end());//快速排序,左闭右开,begin()第一个,end()最后一个后边 
sort(arr.begin(),arr.end(),greater<int>());


bool cmp(pair<int,int> a,pair<int,int> b){//先排第二位,再排第一位 
        //第二位从小到大 
        if(a.second!=b.second)
            return a.second<b.second; 
            
        //第一位从大到小
        return a.first>b.first;        
}

vector(pair<int,int>)arr{{1,9},{2,9}{0,1},(0,0)};
sort(arr.begin(),arr.end(),cmp);

for(auto e:arr){
    cout<<e.first<<' '<<e.second<<endl;
}

//lower_bound()/upper_bound()
lower_bound()//找大于等于x第一个元素
upper_bound()//找大于x的一个元素
大于x的第一个元素的前一个元素便是小于等于x的一个元素
大于等于x的一个元素的前一个元素便是小于x的第一个元素


#include<bits/stdc++.h>
using namespace std;
int mian(){
    vector<int> arr{0,1,1,1,1,8,9,9};
    int pos=upper_bound(arr.begin()+2,arr.end(),0)-arr.begin();
    cout<<pos<<endl;
    return 0;

  

//翻转字符串reverse(起点,终点) 
#include<bits/stdc++.h>
using namespace std;
int mian(){
    vector<int> arr{0,1,1,1,1,8,9,9};
    
    reverse(arr.begin(),arr.end());
    for()
    return 0;

  
  
 //max(a,b);最大值
//max({a,b,c,d})//求里面的最大值 
 //min()同上
 
 
//unique()//消除数组的重复"相邻"元素 
//消重后会在序列尾部产生无效数据,删除这些无效数据,结合erase 
#include<bits/stdc++.h>
using namespace std;
int mian(){
    vector<int> arr{0,1,5,2,6,3,9,2};
    sort(arr.begin(),arr.end()); /
    unique(arr.begin(),arr.end());
    
    arr.earse(unique(arr.begin(),arr.end()),arr.end());
    arr.erase();
    
    return 0;


//数学函数
 abs(-1.0);//取绝对值 
 exp(2); //e的x次方
 log(3);//返回以e为底的ln函数 
 pow(2,3);//求2的3次方
 sqrt(4);//开平方
 ceil(2.1);//向上取整
floor(3.2);//向下取整
round(3.2)//四舍五入到整数


向下取整a/b别用floor(1.0*a/b),直接用a/b
向上取整a/b别用ceil(1.0*a/b),直接用(a+b-1)/b 
开根号向下取整,别用(int)sqrt(a),用二分查找更快
求a的b次方,别用pow(a,b)用快速幂
别用log2(a),用__lg() 
log2(N)=log10(N)/log10(2);//换底公式 

gcd()/lcm()//最大公约数/最小公倍数

int gcd(int a,int b){
    if(a<b)
    swap(a,b);
    return gcd(b,a%b);

int lcm(int a,int b){
    return a/gcd(a,b)*b;
}