纯小白蓝桥杯备赛笔记--DAY6(STL)**重要

vector的定义和特性

 是一个动态数组容器,可以存储一系列相同类型的元素。

- 大小:自动调整大小。

- 元素访问:通过索引来访问元素,索引从0开始,最后一个元素的索引是size()-1。

可以使用【】运算符或at()函数来访问元素。

- 元素添加和删除:可以是使用push_back()函数在vector的末尾添加元素,使用pop_back()函数检查vector是否为空,还可以使用resize()函数调整vector()的大小。

- 迭代器:vector使用了迭代器,可以用于遍历容器中的元素,可以使用begin()函数获得一个元素的迭代器,使用end()函数获取指向最后一个元素之后位置的迭代器。

- 常用函数;

  • push_back()函数:将元素添加到vector的末尾

  • pop_back():删除vector末尾的元素,(注:要保证vector非空)

  • begin和end():指向第一个元素和最后一个元素。

  • vector的排序去重:

    • sort函数排序(从小到大)

    • 去重:unique函数。具体做法:将 重复的元素移动到vector的末尾,并返回第一个指向重复元素的迭代器。最后,可以使用vec.erase函数将重复元素从vector中删除。

stack

在C++中,stack(堆栈)主要用于实现LIFO(后进先出)的数据结构。它通常用于存储和管理具有特定顺序要求的元素,如函数调用的参数、局部变量和返回地址等。当需要对数据进行先进后出的操作时,可以使用stack容器。

  • stack的定义和结构:

    template <class T,class Container=deque<T>> class stack;
  • stack的常用函数:

    函数

    描述

    时间复杂度

    push()

    在栈顶插入元素x

    O(1)

    pop()

    弹出栈顶元素

    O(1)

    top()

    返回栈顶元素

    O(1)

    empty()

    检查栈是否为空

    (返回值为bool类型)

    O(1)

    size()

    返回栈中元素的个数

    O(1)

    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
            //定义stack容器
            stack<int>myStack;
            //向栈中插入元素
            myStack.push(10); 
            myStack.push(20); 
            myStack.push(30); 
            myStack.push(40);
            //获取栈顶元素
            cout<<"栈顶元素是:"<<myStack.top()<<endl;
            //弹出栈顶元素
            myStack.pop();
            cout<<"弹出栈顶元素后,栈顶元素是:"<<myStack.top() <<endl;
            //检查栈是否为空
             if(myStack.empty())
             cout<<"栈顶为空"<<endl;
             else
             cout<<"栈不为空"<<endl;
             //获取栈的大小
             cout<<"栈的大小:"<<myStack.size()<<endl;
             return 0; 
    }
    • 注:stack是不能遍历的。

    • 如果将一个数组中的元素依次放入栈,再依次取出,则可以将数组翻转。

Set

C++中的set主要用于需要去重并按升序排序的情况。 set是一个内部自动有序且不含重复元素的容器,它的主要作用是自动去重并按升序排序。在需要去除重复元素的场景中,如用户ID列表、书籍ISBN号集合等,set是一个理想的选择。

以下是set的一些主要使用场景:

  • 去重数据集:当需要存储不重复的元素时,如统计唯一访问者IP、唯一关键词等,可以使用set来自动去重。

  • 构建有序元素集:如果需要保持数据的唯一性且有序,例如排序后的数组或列表,set可以提供一个有序的环境,方便数据操作和分析。

  • 支持快速查找操作:set基于红黑树实现,可以在O(logN)的时间复杂度下进行插入、删除和查找操作,适合需要快速查找的场景。

  • 格式:

    template <class key,class Compare=less<key>,
                            class Allocator=allocator<key>>
    class set;
  • set集合:

  • 如何实现由大到小排列呢?

、、1
#include<bits/stdc++.h>
using namespace std;
int main()
{
        set<int,greater<int>> mySet;
        mySet.insert(25);
        mySet.insert(17);
        mySet.insert(39);
        mySet.insert(42);
        cout<<"排序後的列表是:"<<endl;
        for(const auto& elem:mySet)
        {
                cout<<elem<<" ";
        }
        cout<<endl;
        return 0;
 } 
 。。2
 #include<bits/stdc++.h>
using namespace std;
struct MyCompare{
        bool operator()(const int& a,const int& b)const{
        return a>b;}
};
int main()
{
        set<int,MyCompare> mySet;
        mySet.insert(25);
        mySet.insert(17);
        mySet.insert(39);
        mySet.insert(42);
        cout<<"排序後的列表是:"<<endl;
        for(const auto& elem:mySet)
        {
                cout<<elem<<" ";
        }
        cout<<endl;
        return 0;
 } 
  • multiset多重集合

    st={x,x,x,y,z} st.erase(st.find(x))//删除的是第一个x

    • 主要区别:允许存储重复的元素。

    • 其中lower_bound()和upper_bound()一般与它组合使用。

    • erase删除的是全部的重复元素,如果只删除一个的情况可以考虑使用迭代器

  • unodered_set无序集合

    • 在set的基础上破坏掉顺序。

    • 底层逻辑是hash。

    • 功能更少。如insert,erase,find,count

  • 操作集合:

#include<bits/stdc++.h>
using namespace std;
int main()
{
        set<int> mySet;
        mySet.insert(25);
        mySet.insert(17);
        mySet.insert(39);
        mySet.insert(39);
        mySet.insert(42);
        cout<<"排序後的列表是:"<<endl;
        for(const auto& elem:mySet)
        {
                cout<<elem<<" ";
        }
        cout<<endl;
        //查找元素
        int setsearch=17;
        auto it=mySet.find(setsearch);//auto表示自動類型推導 
        if(it!=mySet.end())
        cout<<setsearch<<"找到啦"<<endl;
        else
        cout<<"沒有找到"<<endl;
        //移除元素
        int remove_set=39;
        mySet.erase(remove_set);
        //再次輸出
        for(auto &elem:mySet)
        {
                cout<<elem<<" ";
         } 
         cout<<endl;
         //清空集合
         mySet.clear();
         //檢查集合是否為空
         if(mySet.empty())
         cout<<"清空後集合為空"<<endl;
         else
         cout<<"清空后集合不為空"<<endl; 
        return 0;
 } 

Queue(队列)

队列是一种特殊类型的线性数据结构,它拥有两个端点:队头和队尾。在队列中,新元素总是被添加到队尾,而移除操作则发生在队头。这种结构保证了元素的加入和移除顺序,从而实现了先进先出的管理方式。

C++标准库中的std::queue是一个容器适配器,它提供了一组操作来支持队列的基本功能,如push(入队)、pop(出队)、front(访问队头元素)和back(访问队尾元素)等。由于std::queue是一个模板类,它可以与任何类型的数据一起工作,这使得它在处理各种数据类型时非常灵活。

  • 常用函数:

    • push()在队尾插入元素

    • pop()弹出队首元素

    • front()返回队首的元素

    • back()返回队尾元素

    • empty()检查队列是否为空

    • size()返回队列中元素的个数

  • priority_queue优先队列

      元素排列顺序不确定,主要是靠优先级来处理。其中top是最大的,其余元素的大小关系不关心。

    template <class key,class Container=vector<key>,
                            class Compare=less<typename Container::value_type>>
    class priority_queue;
    • 格式

  • 如何改成小根堆:

    //仿函数
    struct Compare{
            bool operator()(int a,int b)
            {
                    return a>b;
            }
    };
    int main()
    {
            priority_queue<int,vector<int>,Compare> pq;//pq定義的優先隊列變量的名稱 
     } 
  • //定义比较函数
    auto compare=[](int a,int b)
    {
            return a>b;
     } ;
     priority_queue<int,vector<int>,decltype(compare)> pq(compare);//decltype用於查詢表達式的類型 

  • deque双端队列

      主要区别就是两端都能进能出。

    template <class key, class Allocator=allocator<key>>
    class deque;
    • 格式

    • 函数中增加的部分:push_back()和pop_front(),即,可对两端进行操作。

  • 两道例题:

CLZ银行只有两个接待窗口,VIP窗口和普通窗口,VIP用户进入

VIP窗口排队,剩下的进入普通窗口排队。现有M次操作,操作有四种类

型,如下:

·IN name V:表示一名叫name的用户到VIP窗口排邦队

·ouTV:表示VIP窗口队头的用户离开排邦队

·IN name N:表示一名叫name的用户到普通窗口排队

·OUTN:表示普通窗口队头的用户离开排队

求M次操作结束后VIP窗口队列和普通窗口队列中的姓名。

#include<bits/stdc++.h>
using namespace std;
int main()
{
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        int m;cin>>m;
        queue<string>V,N;
        while(m--)
        {
                string a;cin>>a;
                if(a=="IN")
                {
                        string b,c;cin>>b>>c;
                        if(c=="V")V.push(b);
                        else N.push(b);
                }
                else
                {
                        string d;cin>>d;
                        if(d=="V")V.pop();
                        else N.pop();
                }
        }
        //輸出(雖然是按需輸出,但是不是遍曆) 
        while(V.size())
        {
                cout<<V.front()<<"\n";
                V.pop();
         } 
         while(N.size())
        {
                cout<<N.front()<<"\n";
                N.pop();
         } 
 } 

每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过几一1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main()
{
        ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
        int m;cin>>m;
        priority_queue<ll,vector<ll>,greater<ll>>pq;//greator把默認的大根堆修改為小根堆 
        for(int i=0;i<m;i++)
        {
                ll x;
                cin>>x;
                pq.push(x);
        }
        ll ans=0;
        while(pq.size()>=2)
        {
                ll x=pq.top();pq.pop();
                ll y=pq.top();pq.pop();
                ans+=x+y;
                pq.push(x+y);                         
        }
        cout<<ans;
        
}

Pair

  • 定义

    • 表示一对值的组合。

    • 结构:

      template<class T1,class T2>
      struct pair{
              T1 first;
              T2 second; 
              //構造函數
              pair();
              pair(const T1& x,const T2& y);
              //比較運算符重載
              bool operator==(const pair& rhs)const;
              bool operator!=(const pair& rhs)const;         
      };
      
    • 使用实例:

      #include<bits/stdc++.h>
      using namespace std;
      int main()
      {
              pair<int,double> p1(1,3.14);
              pair<char,string> p2('a',"hello");
              cout<<p1.first<<","<<p1.second<<endl;
              cout<<p2.first<<","<<p2.second<<endl;
              return 0;
      }
  • pair的嵌套

    • 例子:三维坐标

    • #include<bits/stdc++.h>
      using namespace std;
      int main()
      {
              pair<int,pair<int,int>> p1(3,make_pair(4,5));
              cout<<p1.first<<","<<p1.second.first<<","<<p1.second.second<<endl;
              return 0;
      }
  • pair自带的排序规则

    • 例子:三个二维坐标的排序

      #include<bits/stdc++.h>
      using namespace std;
      int main()
      {
              vector<pair<int,int>>vec;
              vec.push_back(make_pair(3,2));
              vec.push_back(make_pair(1,4));
              vec.push_back(make_pair(2,5));
              sort(vec.begin(),vec.end());
              for(const auto& p:vec)
              {
                      cout<<p.first<<","<<p.second<<endl;
              }
              return 0;
      }

结果为:

  1,4

  2,5

  3,2(产生原因:按照first优先排列)

#include<bits/stdc++.h>
using namespace std;
struct person{
        string name;
        int age;
};
int main()
{
        vector<person>people;
        people.push_back({"Alice",25});
        people.push_back({"Bob",29});
        people.push_back({"Charlie",30});
//創建一個pair向量,每一個pair裡面包括一個person對象和一個評分
        vector<pair<person,int>>scores;
        //添加數據
        scores.push_back({people[0],90}); 
        scores.push_back({people[1],85}); 
        scores.push_back({people[2],95});
        //遍歷pair向量 
        for(const auto& p:scores)
        {
                cout<<"Name:"<<p.first.name<<endl;
                cout<<"Age:"<<p.first.age<<endl;
                cout<<"Scores:"<<p.second<<endl;
                cout<<endl;
        }
        return 0;
}

Map

  • map:是一种关联容器,用来存放一组键值对,按照键来自动进行排序。

  • multimap()可以存储重复的键值对。

    • count函数:有意义,不像map中只能返回0和1.

  • unordered_map

    • 无序,底层哈希函数。

    • 平均复杂度极好。

  • 代码示例:

#include<bits/stdc++.h>
using namespace std;
int main()
{
        //創建併初始化
        map<int,string> mymap={{1,"apple"},{2,"banana"},{3,"orange"}};
        //插入元素
        mymap.insert(make_pair(4,"grapes"));
        //也可以使用
        //mymap.insert({4,"grapes"});
        //查找和訪問元素
        cout<<"Value at key 2:"<<mymap[2]<<endl;
        //遍歷並打印map中的元素
        for(const auto& pair:mymap)
        {
                cout<<pair.first<<","<<pair.second<<endl;
         } 
         //刪除元素
         mymap.erase(3);
         //判斷元素是否存在
         if(mymap.count(3)==0)
         cout<<"刪除成功"<<endl;
         else
         cout<<"刪除失敗"<<endl;
         //清空
         mymap.clear();
         //判斷是否為空
         if(mymap.empty())
         cout<<"空"<<endl;
         else
         cout<<"不空"<<endl; 
        return 0;
}

  • multimap查找元素时不能用方括号:

 
auto range=mymultimap.equal_range(2);
for(auto it=range.first;it!=range.second;it++)
{
cout<<it->first<<","<<it->second<<endl;
}

  • unordered_map遍历时也是没有顺序的。

List

list是双向链表容器,以节点的形式存储元素,并使用指针将这些节点链接。

好处是内存不连续。

特点:

  • 双向性:每一个节点都有前一个和下一个的指针,以常数时间内对任意位置数据进行操作。

  • 动态大小

  • 使用:

#include<bits/stdc++.h>
using namespace std;
int main()
{
        list<int>mylist;
        mylist.push_back(1);
        mylist.push_back(2);
        mylist.push_back(3);
        //在鏈錶頭部插入元素
        mylist.push_front(0);
         //在第一個元素的後一個元素加上元素5
         mylist.insert(++mylist.begin(),5);
         //將list中的元素翻轉
         reverse(mylist.begin(),mylist.end()); 
                 for(int num:mylist)
        {
                cout<<num<<" ";
         } 
         cout<<endl;
         //按區間刪除
         mylist.erase(++ ++mylist.begin(),--mylist.end()) ;
         cout<<"此時鏈錶的大小為:"<<mylist.size()<<endl; 
         //要注意:size返回uint類型,(int)size-1才行 
        return 0;
}
  • list常用函数:

总结

  1. 考查sort函数--3226宝藏排序2

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  int n;
  cin>>n;
  for(int i=1;i<=n;i++)
  {
    cin>>a[i];
  }
  sort(a+1,a+n+1);
  for(int i=1;i<=n;i++)
  {
    cout<<a[i]<<' ';
  }
  return 0;
}

  1. 小兰吃糖果:

我感觉我的智商按在地上摩擦。想得太复杂,其实优先队列就可以解决。。。

#include<bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  int n;cin>>n;
  priority_queue<int>pq;
  ll sum=0;
  for(int i=1;i<=n;i++)
  {
          int x;cin>>x;
          pq.push(x);
          sum+=x;
  }
  ll mx=pq.top();
  if(sum-mx>=mx-1)
  cout<<"Yes"<<'\n';
  else
  cout<<"No"<<'\n';
  return 0;
}

甚至可以直接用变量

 
#include<bits/stdc++.h>
using ll=long long;
using namespace std;
const int N=1e5+9;
int a[N];
int main()
{
  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  int n;cin>>n;
  ll sum=0;
  ll mx=0;
  for(int i=1;i<=n;i++)
  {
          ll x;cin>>x;
          mx=max(mx,x);
          sum+=x;
  }
  if(sum-mx>=mx-1)
  cout<<"Yes"<<'\n';
  else
  cout<<"No"<<'\n';
  return 0;
}

  1. 小兰的字符串()--考查stack

我的想法:左括号和右括号的数量相同,通过率只有80%。遗漏的问题是没有考虑左右括号的顺序问题。所以这道题的最佳选择用栈。

遇到左括号入栈,遇到右括号出栈(配对)。

 
#include<bits/stdc++.h>
using namespace std;
const int N=105;
stack<char>stk;
char s[N];
int main()
{
  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  int n;cin>>n;
  cin>>s+1;
  bool ans=true;
  for(int i=1;i<=n;i++)
  {
          if(s[i]=='(')stk.push('(');
          else
          {
                  if(stk.size()&&stk.top()=='(' )stk.pop();
                  else ans=false;
          }      
  }
  if(stk.size())ans=false;//如果stk里面还有元素也不合法
  cout<<(ans?"Yes": "No")<<'\n'; 
  return 0;
}
  

  1. 快递分拣--map,string,vector的综合应用

#include<bits/stdc++.h>
using namespace std;
map<string,vector<string>>mp;
vector<string>citys;//存储城市的顺序
int main()
{
  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
  int n;cin>>n;
  for(int i=1;i<=n;i++)
  {
          string a,b;cin>>a>>b;
          if(!mp.count(b))citys.push_back(b);//如果b是没有出现过的城市,加入citys
        mp[b].push_back(a);//把单号加入进去   
  }
  for(const auto&city:citys)
  {
          cout<<city<<' '<<mp[city].size()<<'\n';//统计城市下的单号个数
         for(const auto&i:mp[city])
         {
                 cout<<i<<'\n';
          } 
   } 
  return 0; 
}
  
  1. 小明的完美序列--数字的值等于数字的个数

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+9;
map<int,vector<int>>a;
set<int>nums;
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x;cin>>x;
        a[x].push_back(x);
        nums.insert(x);  
    }
    int ans=0;
    for(const auto&num:nums)
    {
        if(a[num].size() != num)//不相符 
        {
                int z=a[num].size();
                while(1)
                {
                        z--;
                        ans++;
                        if(z==num)break;// 减少到相符 
                        else if(z==0)break;//直接减少到0 
                        }
                }
    }
    cout<<ans<<endl;
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值