c++常见容器

🏅vector

容器相关参考

vector的构建

//默认无参构造,此时v无法通过[]操作符访问,会造成内存访问越界
std::vector<int> v;
//预申请内存方式构建,此时v可以通过[]操作符访问
std::vector<int> v(4);
//区间拷贝构造
std::vector<int> v1 = {1,2,3,4};
std::vector<int> v2(v1.begin(),v1.end());
//拷贝构造
std::vector<int> v1 = {1,2,3,4};
std::vector<int> v2(v1);
//n-num构造方式
std::vector<int> v(10,100) //构建10个100的vector
//assign方法
std::vector<int> v;
v.assign(v1.begin(),v1.end());
v.assign(10,100)

vector元素的增加删除

std::vector<int> v;
//尾部插入
v.push_back(2);
//尾部删除
v.pop_back();
//随机位置插入,提供迭代器插入位置
v.insert(v.begin(),100);
//随机位置插入n个元素
v.insert(v.begin(),2,100);
//随机位置擦除,提供迭代器擦除位置
v.erase(v.begin());//擦除到迭代器位置以前的所有元素
v.erase(v.end());//错误异常用法,删除尾部元素应该使用v.pop_back()函数
//随机区间擦除,提供迭代器位置区间
v.erase(v.begin(),v.end()); //此时相当于清空操作类似v.clear();

std::vector::clear与std::vector::resize


//c++先clear()再resize()会直接报错
std::vector<int> vec;
vec.clear();
vec.resize(); //error

vector 自定义排序问题

//自定义升序排序函数
auto compareFuc = [](_type_def& a,_type_def& b){
  return a>b;
};
//自定义降序排序函数
auto compareFuc = [](_type_def& a,_type_def& b){
  return a>b;
};
//sort 函数
std::sort(vec.begin(),vec.end(),compreFuc)

🏅deque

双端队列容器,与vector类似,可以在头部和尾部方便的插入删除元素,deque不能保证所有元素存储在一个连续的内存空间中

构建方式

#include <deque>
#include <iostream>
int main()
{
  std::deque<int> a;//声明一个空的双端队列
  std::deque<int> a(4);//声明一个4元素大小的双端队列
  std::deque<int> a(4,1);//声明一个4个元素大小的双端队列,指定每个元素的值
  std::deque<int> b(a);//拷贝构造
  std::deque<int> b(a.begin(),a.end());//指定区间的拷贝构造
  //从数组构造
  int a[] = {1,2,3,4,5};
  std::deque<int> b(a,a+5);
  return 0;
}

增加删除

std::deque<int> d;
d.push_back(1); // 尾部插入元素
d.push_front(1);// 头部插入元素
d.pop_back();// 尾部删除元素
d.pop_front();// 头部删除元素

//随机位置插入
d.insert(d.begin()+1,1); //begin()+1位置插入一个元素1
d.insert(d.begin()+1,2,1); //begin()+1位置插入2个元素1
//随机位置删除
d.erase(d.begin()+2); //删除begin()+2位置的元素
d.erase(d.begin()+2,d.end());//删除begin()+2,end()之间的元素

//赋值 assign
d.assign(2,1);

🏅queue

先进先出队列

构建函数

#include <queue>
std::queue<int> a; //默认构造函数构建
std::queue<int> b(a); //拷贝构造函数构建

增加删除元素

#include<queue>
std::queue<int> a;
a.push(1);//队列入队1个元素
std::cout<<a.size()<<std::endl;//输出1
//pop
a.pop();//出队一个元素
std::cout<<a.size()<<std::endl;//输出0
//获取队首元素
int s = a.front();
//清空队列
while(!a.empty()){
  a.pop();
}

🏅list

链表在对数据进行插入和删除是比顺序存储的线性表有优势,
因此在插入和删除操作频繁的应用场景中,
使用list和forward_list比使用array、vector和deque效率要高很多。
list为双向链表
forward_list是单向链表
#include <forward_list>
#include <list>
int main()
{
    //std::list<int> l = {1,2,3,4,5};
    std::forward_list<int> numbers = {1,2,3,4,5,4,4};
    std::cout << "numbers:" << std::endl;
    for (auto number : numbers)
    {
        std::cout << number << std::endl;
    }
    numbers.remove(4);
    std::cout << "numbers after remove:" << std::endl;
    for (auto number : numbers)
    {
        std::cout << number << std::endl;
    }
    //链表的插入删除元素
    l.push_back(1); // 尾部插入元素
    l.push_front(1); // 头部节点元素
    l.emplace_back(1); // 右值尾部插入,避免对象的拷贝消耗
    l.emplace_front(1); // 右值头部插入
    l.pop_back(); // 尾部弹出元素
    l.pop_front(); // 头部弹出元素
    //擦除元素
    l.erase(l.begin()+1); // l.begin()+1擦除该元素
    l.erase(l.begin()+1,l.end()); // 擦除l.begin()+1到l.end()之间的元素
    return 0;
}

🏅array

std::array是c++11新增的静态数组类

#include <array>
int main()
{
    //构建方式
    //std::array<int,4> arrayDemo{{1,2,3,4}};
    std::array<int, 4> arrayDemo = { 1,2,3,4 };
    std::cout << "arrayDemo:" << std::endl;
    for (auto itor : arrayDemo)
    {
        std::cout << itor << std::endl;
    }
    int arrayDemoSize = sizeof(arrayDemo);
    std::cout << "arrayDemo size:" << arrayDemoSize << std::endl; // 4*4 =16
    return 0;
    //arrayDemo.front() 获取数组首部元素
    //arrayDemo.back() 获取数组尾部元素
    //std::array重载了[]操作符,支持arrayDemo[i]访问
}

🏅set

std::unordered_set的数据存储结构也是哈希表的方式结构,
除此之外,std::unordered_set在插入时不会自动排序,这都是std::set表现不同的地方。
#include <iostream>
#include <string>
#include <unordered_set>
#include <set>
int main()
{
    std::unordered_set<int> unorder_set;
    unorder_set.insert(7);
    unorder_set.insert(5);
    unorder_set.insert(3);
    unorder_set.insert(4);
    unorder_set.insert(6);
    std::cout << "unorder_set:" << std::endl;
    for (auto itor : unorder_set)
    {
        std::cout << itor << std::endl; // 无序,不会排序,按插入的循序打印 7,5,3,4,6
    }

    std::set<int> set; // 有序,在插入时会自动排序
    set.insert(7);
    set.insert(5);
    set.insert(3);
    set.insert(4);
    set.insert(6);
    std::cout << "set:" << std::endl;
    for (auto itor : set)
    {
        std::cout << itor << std::endl;// 有序3,4,5,6,7
    }
}

🏅map

std::unordered_map与std::map用法基本差不多,但STL在内部实现上有很大不同
std::map使用的数据结构为二叉树,而std::unordered_map内部是哈希表的实现方式,
哈希map理论上查找效率为O(1)。但在存储效率上,哈希map需要增加哈希表的内存开销。
#include <iostream>
#include <string>
#include <unordered_map>
#include <map>
int main()
{
    std::unordered_map<std::string, std::string> mymap =
    {
        { "house","maison" },
        { "apple","pomme" },
        { "tree","arbre" },
        { "book","livre" },
        { "door","porte" },
        { "grapefruit","pamplemousse" }
    };
    unsigned n = mymap.bucket_count();// 使用的内存桶数量
    std::cout << "mymap has " << n << " buckets.\n";
    for (unsigned i = 0; i<n; ++i)    // 遍历每一个桶,每个桶内可能存在多个数据 
    {
        std::cout << "bucket #" << i << " contains: ";
        for (auto it = mymap.begin(i); it != mymap.end(i); ++it)// 遍历每个桶内存储的数据
            std::cout << "[" << it->first << ":" << it->second << "] ";
        std::cout << "\n";
    }
    return 0;
}

🏅algothrim

参考一
参考二

头文件:

非修改序列算法

  • find
  • find_if
  • find_first_of
  • for_each
  • count
  • count_if
  • search
  • search_n
  • find_end

⏰代码演示如下:

#include <algothrim>
#include <vector>
#include <list>
//一元函数操作符
bool is3(int x)
{
  return x==3;
}
auto is3_lambda = [](int x){return x==3;};

struct Is3
{
  //重载()操作符
  bool operator()(int x)
  {
    return x==3;
  }
}

int main()
{
    //---------------------------------------find--------------------------------------------------
    std::vector<int> v = {1,2,3,4,5};
    std::vector<int> c = {3,4};
    //std::vector<int>::iterator iter = std::find(v.begin(),v.end(),3);
    auto iter = std::find(v.begin(),v.end(),3); //返回迭代器位置
    if(iter!=v.end()){std::cout<<"找到"<<std::endl;}
    //--------------------------------------find_if-------------------------------------------------
    std::vector<int>::iterator iter = std::find_if(l.begin(),l.end(),is3); //调用函数对象
    std::vector<int>::iterator iter = std::find_if(l.begin(),l.end(),is3_lambda); //调用lambda匿名函数对象
    std::vector<int>::iterator iter = std::find_if(l.begin(),l.end(),Is3());//调用仿函数对象
    if(iter!=l.end()){std::cout<<"找到"<<std::endl;}
    //------------------------------------find_first_of---------------------------------------------
    auto iter = std::find_first_of(v.begin(),v.end(),c.begin(),c.end()); //c与v只要有一个元素匹配则返回该元素的位置
    auto isMod = [](int x,int s){
      if(x%s==0) return 1;
      else return 0;
    }
    auto iter = std::find_first_of(v.beign(),v.end(),c.beign(),v.end(),isMod);//返回两个序列整除的第一个数字所在位置即v序列中3的位置
    if(iter!=v.end()){
      std::cout<<"找到,位于v:"<<std::distance(v.begin(),iter)<<std::endl;
    }
    //----------------------------------------find_end----------------------------------------------
    //std::find_end用于查找容器内子序列最后一次出现的位置,类似于find和finf_of,可接受一个二元操作符函数作为Pred
    std::vector<int> v1 = {1,2,3,4,5,6,7,8};
    std::vector<int> v2 = {4,5,6}; //子序列
    auto result = std::find_end(v1.beign(),v1.end(),v2.begin(),v2.end()); 
    if(result!=v1.end()){
      std::cout<<"找到子序列位置:"<<std::distance(v1.begin(),result)<<std::endl;
    }
    auto equal_lambda = [](int a,int b){return a==b;}
    auto result = std::find_end(v1.begin(),v1.end(),v2.begin(),v2.end(),equal_lambda);//调用自定义pred函数进行子序列匹配查询
    if(result!=v1.end()){
      std::cout<<"找到子序列位置:"<<std::distance(v1.begin(),result)<<std::endl;
    }
    //----------------------------------------for_each-----------------------------------------------
    // for_each 类似python语法中的map函数
    std::vector<int> a = {1,2,3,4,5};
    auto lambdaPrint = [](int const& s){std::cout<<s<<" ";}
    std::for_each(a.cbegin(),c.cend(),lambdaPrint); //逐个元素打印输出
    struct Sum
    {
      int sm{0};
      void operator()(int x){
        sm+=x;
      }
      int getSum(){
        return sm;
      }
    }
    std::for_each(a.begin(),a.end(),Sum()); //累加
    //------------------------------------------count------------------------------------------------
    std::vector<int> a = {1,2,3,4,5,6,7,8,9};
    const int num = std::count(a.cbegin(),c.cend(),4);//查找值为4的元素个数
    //----------------------------------------count_if-----------------------------------------------
    std::vector<int> a = {1,2,3,4,5,6,7,8,9};
    const int num = std::count_if(a.cbegin(),a.cend(),[](const int x){return x%4==0;}); //查找被4整除的元素个数
    //-----------------------------------------search------------------------------------------------
    std::vector<int> a = {1,2,3,4,5,6,7,8,9};
    std::vector<int> b = {3,4,5};
    auto result = std::search(a.beign(),a.end(),b.begin(),be.end()); //查询子序列b在a中的位置
    if(result != a.end())
    {
      std::cout<<"子序列位置找到"<<std::distance(a.begin(),result)<<std::endl;
    }
    //二元谓词
    auto compare = [](int aa,int bb){
      if(aa>bb) return 1;
      else return 0;
    }
    auto result = std::search(a.beign(),a.end,b.begin(),b.end(),compare); // 查找比子序列b大的序列位置
}

修改序列算法

  • random_shuffle 随机打乱指定范围内元素位置
  • replace 将容器中指定元素的值替换为指定值
  • replace_if 类似于replace
  • replace_copy 与replace类似,同时将容器中元素拷贝到另一个容器
  • fill && fill_n 给定范围内的元素赋值为指定值
  • remove 将一个范围中值等价于给定值的元素删除、并返回新结尾迭代器
  • reverse 反转排序指定范围内的元素
  • unique 删除指定范围中的所有连续重复元素,仅仅留下每组等值元素中的第一个元素
  • transform 对范围中的每个元素调用某函数,并将新值复制到另一个范围
  • copy && copy_if

代码演示如下:

#include <iostream>
#include <vector>
#include <algothrim>
#include <iterator> 
int main()
{
  std::vector<int> a =  {1,2,3,4,5,6};
  //-------------------------------------------random_shuffle
  std::random_shuffle(a.begin(),b.end()); //随机乱序整个序列a
  std::for_each(a.begin(),a.end(),[](int x){std::cout<<x<<" ";}); // 打印乱序后的序列
  std::cout<<std::endl;
  //-------------------------------------------replace
  std::replace(a.begin(),a.end(),3,55);//替换所有元素值为3的元素为55,a = {1,2,55,4,5,6}
  std::for_each(a.begin(),a.end(),[](int x){std::cout<<x<<" ";}); // 打印替换后的元素序列
  std::cout<<std::endl;
  //-------------------------------------------replace_if
  std::replace_if(a.begin(),b.end(),[](int x){return x%4==0;},66); //匿名一元谓词返回为true的位置替换为66,a={1,2,3,66,5,6}
  std::for_each(a.begin(),a.end(),[](int x){std::cout<<x<<" ";}); // 打印结果
  std::cout<<std::endl;
  //-------------------------------------------replace_copy
  //此时类似于replace只是将替换后的序列拷贝到另一个容器中
  std::replace_copy(a.begin(),a.end(),std::ostream_iterator<int>(std::cout," "),3,22);
  std::cout<<"\n";
  std::vector<int> b(a.begin(),a.end());
  std::replace_copy(a.begin(),a.end(),b.begin(),3,22);
  //-------------------------------------------replace_copy_if
  /*
  类似replace_copy,只是将指定值替换为一元谓词
  */
  std::replace_copy_if(a.beign(),a.end(),std::ostream_iterator<int>(std::cout," "),[](int x){return x%6==0;},66);
  std::cout<<"\n";
  //-------------------------------------------fill && fill_n
  std::fill(a.begin(),a.end(),-1); // a={-1,-1,-1,-1,-1,-1}
  std::fill_n(a.begin(),2,-1); // a={-1,-1,3,4,5,6};
  //-------------------------------------------remove && remove_if && remove_copy && remove_copy_if
  auto newEnd = std::remove(a.beign(),a.end(),3); //删除指定值的元素,不改变容器大小,返回删除后的序列最后位置
  std::for_each(a.begin(),newEnd,[](int x){std::cout<<x<<" ";});
  std::cout<<std::endl;
  std::string str2 = "Text\n with\tsome \t  whitespaces\n\n";
  auto newEnd = std::remove_if(str2.begin(),str2.end(),[](unchar x){return std::isspace(x);});//删除字符串str2中的空格
  /*
  remove_copy类似于remove,移除指定元素后拷贝到指定容器中
  */
  std::vector<int> b(a.size());
  std::remove_copy(a.begin(),a.end(),b.begin(),3);//移除所有元素3并将移除后的序列拷贝到容器b中
  /*
  remove_copy_if类似与remove_if根据一元谓词结果删除特定元素后拷贝到另一个容器中
  */
  std::remove_copy_if(a.begin(),a.end(),b.beign(),[](int x){return x%2==0;});//删除所有能被2整除的元素并将删除后的新序列拷贝到b中
  //-------------------------------------------reverse && reverse_copy
  std::vector<int> v{1, 2, 3};
  std::reverse(v.begin(), v.end());
  for (auto e : v)
      std::cout << e;
  std::cout << '\n';
  int a[] = {4, 5, 6, 7};
  std::reverse(std::begin(a), std::end(a));
  for (auto e : a)
      std::cout << e;
  /*
  reverse_copy类似reverse,只是将反序后的序列拷贝到另一个容器中
  */
  std::vector<int> vv = {1,2,3,4,56};
  std::vector<int> des(vv.size());
  std::reverse_copy(vv.begin(),vv.end(),des.begin());
  return 0;
  //-------------------------------------------unique && unique_copy
  std::vector<int> a = {1,1,2,3,4,4,5,6,5,5};
  auto nEnd = std::unique(a.begin(),a.end()); //不改变a序列长度 a={1,2,3,4,5,6,5,0}
  a.erase(nEnd,a.end()); //擦除尾部元素 a={1,2,3,4,5,6,5}
  /*
  unique_copy 类似unique,去重后将去重后的新序列拷贝到新序列中
  */
  std::vector<int> b(a.size());
  std::unique_copy(a.begin(),a.end(),b.begin()); // 第一种使用方法
  std::unique_copy(a.beign(),a.end(),b.beign(),[](int aa,int bb){return aa==1 && bb==1;});
  //-------------------------------------------transform
  auto add1 = [](int x){return x+1;}
  std::vector<int>des(a.size());
  std::transform(a.begin(),a.end(),des.begin(),add1); //所有元素+1并拷贝到新序列des中
  //-------------------------------------------copy && copy_if
  /*
  实现容器之间的数据copy作用
  */
  std::vector<int> bb(a.size());
  std::copy(a.begin(),a.end(),bb.beign());//单纯容易元素拷贝操作
  bb.clear();//清空bb容器
  std::copy_if(a.begin(),a.end(),std::back_inserter(bb),[](int x){return x==3;});//按照一元谓词返回结果拷贝元素
}
posted @   DumoIO  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示