• STL中的基本数据结构与算法


    目录

    所在位置

    入门篇:

    STL

    STL(Standard Template Library)是C++的标准模板库,很多竞赛常用的数据结构、算法在STL中都有,熟练掌握能极大简化编程。

    一、STL容器

    STL的容器分为两类

    ​ ①顺序式/序列容器(底层主要采用向量和链表)
    ​ 常见的有:vector、list、stack、queue、deque、priority_queue等
    ​ vector与list优缺点正好相反

    ​ ②关联式/关联容器(底层主要采用平衡二叉搜索树结构)
    ​ 常见的有:set、map、multiset、multimap等

    简要特性

    • stack
      ①先进后出
      离自己最近的符合某条件的->单调栈
    • queue
      先进先出
    • list

    通用操作

    //迭代器
    x.begin();//返回容器首个元素的迭代器
    x.end();//*返回容器尾元素的后一个位置的迭代器
    //反向迭代器
    x.rbegin();//返回容器尾元素的迭代器
    x.rend();//返回容器首元素的前一位置的迭代器
    
    x.size();//返回容器元素数量
    x.empty;//判断容器是否为空
    
    //非通用
    x.clear();//删除所有元素,仅vector、map、set...
    d[];//像数组一样,支持随机访问,仅vector、map...
    

    接下来先具体介绍几种常见的容器。

    1.1 vector——向量

    STL中的vector向量是一种动态数组(可变长数组),在运行时能根据需要自动改变数组大小。

    特点:可随机访问,但插入删除较慢

    需要掌握

    • 定义vectorv

      #include <bits/stdc++.h>//加入相关头文件:万能头,包含<vector>
      vector <int> v;
      
    • 插入 push_back();

      v.push_back(i);//加入至尾部
      v.insert(v.begin() + i, value);//加入至v[i]
      
    • 访问

      //支持随机访问
      for(int i = 0; i < v.size(); i++)
         cout << v[i] << " ";
      //迭代器访问
      for(auto it = vi.begin(); it!=vi.end(); it++)
          cout<<*it<<' '<<endl;
      
      //查找
      v.find(value);//返回其迭代器
      
    • 删除

      v.pop_back();//弹出尾部
      v.erase(iterator it)//删除某个迭代器
      v.erase(iterator first, iterator end);//删除区间[begin,end)
      v.clear();//删除所有元素
      

    1.2 stack——栈

    栈是一种先进后出的容器(可以理解为泡腾片的拿入拿出)

    栈顶添加,栈顶弹出

    需要掌握

    • 定义stack s

      #include <bits/stdc++.h>//万能头,作用等同于#include <stack>
      stack <int> s;
      
    • 添加 push

      s.push(key);//入栈至栈顶
      
    • 访问 top

      s.top();//只能访问栈顶
      
    • 删除 pop

      s.pop()//只能弹出栈顶
      

    1.3 queue——队列

    queue是一种先入先出的容器。

    队尾添加,队首弹出

    需要掌握

    • 定义queue q

      #include <bits/stdc++.h>//万能头,等同于#include <queue>
      queue <int> q;
      
    • 添加 push

      q.push(key);//入队至队尾
      
    • 访问 front、back

      q.front();//访问队首
      q.back();//访问队尾
      
    • 删除 pop

      q.pop()//只能弹出队首
      

    1.4 list——双向列表

    STL的list是数据结构中的双向链表,内存空间不连续,通过指针来访问

    特点:可高效率在任意地方删除与插入,但不支持随机访问(访问较慢)

    需要掌握

    • 定义

      list<int> list1;
      
    • 插入

      list1.push_front(value);//头插
      list1.push_back(value);//尾插
      list1.insert(pos,num);//在pos迭代器位置插入元素num。
      list1.insert(pos,n,num)//在pos迭代器位置插入n个元素num。
      list1.insert(pos,beg,end)//在pos迭代器位置插入区间为[beg,end)的元素。
      
    • 访问

      list1.front();//返回第一个元素
      list1.back();//返回最后一个元素
      for (auto it = list1.begin(); it != list1.end(); it++)//迭代访问
          cout << *it << " ";
      
    • 删除

      list1.pop_back();//尾删
      list1.pop_front();//头删
      list1.erase(pos);//删除pos迭代器位置的元素
      list1.clear();//删除所有
      

    2.1 set

    set是一个自动实现无重且按一定规则排序的集合

    需要掌握

    • 定义 set s;

      #include <bits/stdc++.h>//万能头,包含<queue>
      set <int> s;
      
    • 插入 insert

      s.insert(value);//插入元素进集合(自动去重)
      
    • 查找 find

      //查找值为value的迭代器find(value)
      auto it=s.find(value);
      //查找set中是否含有value
      if(s.find(value) != s.end())
      //可使用upper_bound()、lower_bound()等
      
    • 遍历输出 *it

      //迭代器访问
      for(auto it=s.begin();it!=s.end();it++){
          cout<<*it<<endl;
      }
      
    • 删除某个值 erase

      //删除某值
      s.erase(value);
      //删除某迭代器
      s.erase(iterator it);
      //删除某迭代器区间
      s.erase (iterator first, iterator end);
      

    2.2 map

    map是一个无重有序的不同类型之间映射的集合

    是一组键值对的组合,按键排序,键和值可以是任意的类型。

    需要掌握

    • 定义 map<typename1,typename2> mp;

      map<string, int> mp;
      
    • 设置键值对

      mp.insert(make_pair("haha",1));//先输入给一个pair
      mp("haha") = 1;//或者直接赋值
      
    • 迭代访问输出键值

      for(auto it=mp.begin();it!=mp.end();it++)
          cout<<it->first<<" "<<it->second<<endl;
      
    • 查找

      //查找键为key的迭代器
      auto it = mp.find('a');
      //可使用upper_bound()、lower_bound()等
      
    • 删除

      //删除某个迭代器
      mp.erase(iterator it);
      //删除所有
      mp.clear()
      

    二、常用算法

    1. lower_bound()、upper_bound()

    lower_bound()、upper_bound()可以分别求出以数组中或容器中当前元素为下界/上界的下一个元素

    但是前提是数组或容器本身已经是有序的!!【已排序的数组 或map以及set】

    lower_bound(first, end, val)//找到有序容器或数组中第一个大于等于val的位置
    upper_bound(first, end, val)//找到有序容器或数组中第一个小于等于val的位置
    //first、end可以是容器的迭代器,或者数组的地址
    

    2. next_permulation()

    next_permulation()——生成比当前数组/字符串排列大的下一个排列

    next_permulation(a,a+n);//根据数组a的排列找出下一个比它排列大的数组,并更新a
    
    next_permulation(s.begin(),s.end());//根据字符串s的排列找出下一个比它排列大的字符串,并更新s
    

    3.sort()

    sort()——可以实现对数、字符串、二元组pair、结构体甚至STL容器的排序

    默认升序排序,可自定义排序规则cmp

    此处先简要介绍对基本类型以及字符串的排序

    /* 整型数组的排序 */
    bool cmp(int a, int b)//自定义整型的降序cmp
        return a > b;
    int a[N];
    for(int i = 0; i < n; i++) 
        cin << a[i];
    sort(a, a + n);//对数组a[0]-a[n-1]的元素升序排序![)
    sort(a, a + n, cmp);//默认升序,我们可以写个降序的cmp
    
    
    /* 字符串对字符的排序 */
    string a;
    //scanf("%s", &a[0]);//用scanf()输入只需要a[0]首地址
    cin >> a;
    sort(a.begin(), a.end());
    printf("%s",a.c_str());//不能用cout输出字符串
    
    

    以上都是sort(a, b)的形式,默认以升序排序

    自定义排序规则,需要在使用sort时添加自定义的比较函数cmp()

    /* 对整型 */
    sort(a, a+n, cmp);
    //默认升序
    bool cmp(int a,int b)
      return a<b;
    //降序
    bool cmp(int a,int b)
      return a>b;
    
    
    /* 对字符串 */
    sort(a.begin(), a.end(), cmp)
    //默认升序
    bool cmp(char a,char b)
        return a<b;
    //降序
    bool cmp(char a,char b)
        return a>b;
    

    4.bitset()位操作

    bitset可以理解为一个存放二进制的数组,我们可以将整型、字符串存入bitset中。

        //初始化与各类型的输出
        bitset<5> b;//初始化5位的二进制位数组,默认均为0
        cout << b << endl;;
    
        int u1 = 1;
        bitset<5> b1(u1);//将整型初始化为5位二进制,不足左边补0
        cout << b1 << endl;//u1 = 1,则被初始化为00001
    
        string s2 = "1101";
        bitset<5> b2(s2);//将字符串初始化为5位二进制,不足左边补0
        cout << b2 << endl;;//s2=”1101“,则被初始化为”01101“
    
        string s3 = "110100";
        bitset<5> b3(s3);//当字符串足够时,则取左边5个
        cout << b3 << endl ;//s3为”1101“,则被初始化为”11010“
    
        //bitset<5> b(s, pos, n); //取字符串的s[pos]开始,n位长度
        bitset<5> b4(s3, 1, 2); //“10”—>00010
        cout << b4 << endl;
    
        cout << (b4 >> 1) << endl;//右移一位
    
    
        //注意是逆序存储进下标的,下标低的表示低位
        for(int i = 0; i< 5; i++)
            cout<< b4[i];
        cout << endl;
    
        //其它操作
        cout << endl << b.any();//b中是否存在1的二进制位?
        cout << endl << b.none();//b中不存在1吗?
        cout << endl << b.count();//b中1的二进制位的个数
        cout << endl << b.size();//b中二进制位的个数
        cout << endl << b.test(2);//测试b下标为2处是否二进制位为1
        cout << endl << b4.test(1);//测试b4下标为2处是否二进制位为1
    
        b.set(4);//下标4变为1
        b.reset();//所有位归零
        b.reset(3);//下标3处归零
        b.flip();//b的所有二进制位逐位取反
    
  • 相关阅读:
    SDRAM(3):刷新和仲裁
    SDRAM(2):初始化
    SDRAM(1):基本介绍
    计数器(3):避免多计少计
    协议——SPI
    matlab数字图像处理 入门基础
    gVim编辑器——基本设置、常用命令、代码片段
    Pomelo的Router
    Pomelo聊天室框架
    Pomelo术语解释
  • 原文地址:https://www.cnblogs.com/Hokkaido-JL/p/13818634.html
Copyright © 2020-2023  润新知