stl六大组件之算法(代码片段)

森明帮大于黑虎帮 森明帮大于黑虎帮     2022-12-19     271

关键词:

文章目录

56、STL六大组件之遍历算法

/*
    #include<algorithm> 算法
    #include<functional> 函数对象
    #include<numbers> 算法补充

    通过迭代器来操作容器中的元素

    for_each(begin(),end(),callback);遍历容器算法,将迭代器指向的元素当参数来调用普通函数或者函数对象或者lambda表达式,
    返回值为回调函数

    transform(begin1(),end1(),begin2(),callback)将指定容器区间的元素搬到另一个容器
    不会给目标容器预先分配内存,要手动预先分配好内存

    operator2 transform(begin1(),end1(),begin2(),callback)
    begin1() 原容器开始迭代器
    end1() 原容器结束迭代器
    begin2() 目标容器开始迭代器
    callback 回调函数,可以是普通函数,函数对象(仿函数),lambda表达式
    operator2 返回目标容器的特定位置迭代器

    operator3 transform(begin1(),end1(),begin2(),begin3(),callback)
    begin1() 原容器开始迭代器
    end1() 原容器结束迭代器
    begin2() 目标容器开始迭代器
    begin3() 目标容器开始迭代器
    callback 回调函数,可以是普通函数,函数对象(仿函数),lambda表达式
    operator3 返回目标容器的特定位置迭代器
*/

代码如下:

#include<iostream>

#include<algorithm>

#include<vector>
#include<string>
/*
    #include<algorithm> 算法
    #include<functional> 函数对象
    #include<numbers> 算法补充

    通过迭代器来操作容器中的元素

    for_each(begin(),end(),callback);遍历容器算法,将迭代器指向的元素当参数来调用普通函数或者函数对象或者lambda表达式,
    返回值为回调函数

    transform(begin1(),end1(),begin2(),callback)将指定容器区间的元素搬到另一个容器
    不会给目标容器预先分配内存,要手动预先分配好内存

    operator2 transform(begin1(),end1(),begin2(),callback)
    begin1() 原容器开始迭代器
    end1() 原容器结束迭代器
    begin2() 目标容器开始迭代器
    callback 回调函数,可以是普通函数,函数对象(仿函数),lambda表达式
    operator2 返回目标容器的特定位置迭代器

    operator3 transform(begin1(),end1(),begin2(),begin3(),callback)
    begin1() 原容器开始迭代器
    end1() 原容器结束迭代器
    begin2() 目标容器开始迭代器
    begin3() 目标容器开始迭代器
    callback 回调函数,可以是普通函数,函数对象(仿函数),lambda表达式
    operator3 返回目标容器的特定位置迭代器
*/

//普通函数
void MyPrint(std::string& str)
    std::cout<<str<<" ";

//函数对象仿函数
class Print
public:
    void operator()(std::string& str)
        std::cout<<str<<" ";
    
;
void Func1()
    std::vector<std::string> vec1"tom","jery","rose";
    std::for_each(vec1.begin(),vec1.end(),MyPrint);
    std::cout<<std::endl;
    std::for_each(vec1.begin(),vec1.end(),Print());
    std::cout<<std::endl;
    std::for_each(vec1.begin(),vec1.end(),[&](std::string& str)->void
        std::cout<<str<<" ";
    );
    std::cout<<std::endl;


std::string& MyPrint2(std::string& str)
    return str;

void Func2()
    std::vector<std::string> vec1"aaa","jery","bbb";
    std::vector<std::string> vec2;
    vec2.resize(vec1.size());
    std::transform(vec1.begin(),vec1.end(),vec2.begin(),MyPrint2);
    std::for_each(vec2.begin(),vec2.end(),[=](std::string& str)->void
        std::cout<<str<<" ";
    );
    std::cout<<std::endl;
    std::for_each(vec2.begin(),vec2.end(),Print());
    std::cout<<std::endl;


_Uint32t AddNum(_Uint32t a,_Uint32t b)
    return a+b;

void Func3()
    std::vector<int> vec11,2,3,4;
    std::vector<int> vec210,20,30,50;
    std::vector<int> vec3;
    vec3.resize(vec1.size());
    std::transform(vec1.begin(),vec1.end(),vec2.begin(),vec3.begin(),AddNum);
    std::for_each(vec3.begin(),vec3.end(),[&](_Uint32t a)->void
        std::cout<<a<<" ";
    );
    std::cout<<std::endl;

int main()
    Func1();
    Func2();
    Func3();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
tom jery rose 
tom jery rose
tom jery rose
aaa jery bbb
aaa jery bbb
11 22 33 54 
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> 

57、STL六大组件之查找算法1

/*
    iterator find(begin,end,val)

    iterator find_if(begin,end,func)

    begin();被查找的容器的开始迭代器
    end(); 被查找的容器的结束迭代器
    func 查找条件的函数或者函数对象(谓词)
*/

代码如下:

#include<iostream>

#include<vector>
#include<string>
#include<algorithm>
#include<functional>
/*
    iterator find(begin,end,val)

    iterator find_if(begin,end,func)

    begin();被查找的容器的开始迭代器
    end(); 被查找的容器的结束迭代器
    func 查找条件的函数或者函数对象(谓词)
*/


void Func1()
    std::vector<int> vec11,2,3,4,5,6;
    std::vector<int>::iterator iter1=std::find(vec1.begin(),vec1.end(),3);
    if(iter1!=vec1.end())
        std::cout<<*iter1<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    
    auto iter2=std::find(vec1.begin(),vec1.end(),10);
    if(iter2!=vec1.end())
        std::cout<<*iter2<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    bool operator==(const A& a)
        return (id_==a.id_)&&(name_==a.name_);
    
    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    
private:
    _Uint32t id_;
    std::string name_;
;

void Func2()
    std::vector<A> vec1A(1,"tom"),A(2,"jery");
    auto iter1=std::find(vec1.begin(),vec1.end(),A(2,"jery"));
    if(iter1!=vec1.end())
        std::cout<<(*iter1).GetId()<<" "<<(*iter1).GetName()<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


struct MyFind1
public:
    bool operator()(_Uint32t id)
        return id=3;
    
;

struct MyFind2:public std::binary_function<_Uint32t,_Uint32t,bool>
    bool operator()(_Uint32t a,_Uint32t b) const
        return a==b;
    
;

void Func3()
    std::vector<int> vec11,2,3,4;
    auto iter1=std::find_if(vec1.begin(),vec1.end(),MyFind1());
    if(iter1!=vec1.end())
        std::cout<<*iter1<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    
    auto iter2=std::find_if(vec1.begin(),vec1.end(),std::bind2nd(MyFind2(),2));
    if(iter2!=vec1.end())
        std::cout<<*iter2<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


struct MyFind3
    bool operator()(A& a)
        return (a.GetId()==1&&a.GetName()=="tom");
    
;

void Func4()
    std::vector<A> vec1A(1,"tom"),A(2,"jery"),A(3,"rose");
    auto iter1=std::find_if(vec1.begin(),vec1.end(),MyFind3());
    if(iter1!=vec1.end())
        std::cout<<(*iter1).GetId()<<" "<<(*iter1).GetName()<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


struct MyFinc4:public std::binary_function<A,A,bool>
    bool operator()(A& a1,A& a2) const
        return a1.GetId()==a1.GetId()&&a1.GetName()==a1.GetName();
    
;

void Func5()
    std::vector<A> vec1A(1,"tom"),A(2,"jery");
    auto iter1=std::find_if(vec1.begin(),vec1.end(),std::bind2nd(MyFinc4(),A(1,"tom")));
    if(iter1!=vec1.end())
        std::cout<<(*iter1).GetId()<<" "<<(*iter1).GetName()<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

int main()
    Func1();
    Func2();
    Func3();
    Func4();
    Func5();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
3
not find
2 jery
1
2
1 tom
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug>

58、STL六大组件之查找算法2

查找相邻的重复元素
    
iterator adjacent_find(begin(),end())

iterator adjacent_find(begin(),end(),func) func可以理解成一个函数对象

代码如下:

class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    
private:
    _Uint32t id_;
    std::string name_;
;

void Func1()
    std::vector<std::string> vec1"tom","jery","jery","rose";
    std::vector<std::string>::iterator iter1=std::adjacent_find(vec1.begin(),vec1.end());
    if(iter1!=vec1.end())
        std::cout<<*iter1<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

    std::vector<std::string> vec2"tom","jery","rose";
    auto iter2=std::adjacent_find(vec2.begin(),vec2.end());
    if(iter2!=vec2.end())
        std::cout<<*iter2<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


struct MyFind1
    bool operator()(A& a,A& b)
        return a.GetId()==b.GetId()&&a.GetName()==b.GetName();
    
;
void Func2()
    std::vector<A> vec1A(1,"tom"),A(2,"jery"),A(2,"jery");
    auto iter1=std::adjacent_find(vec1.begin(),vec1.end(),MyFind1());
    if(iter1!=vec1.end())
        std::cout<<(*iter1).GetId()<<" "<<(*iter1).GetName()<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
jery    
not find
2 jery
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug>
二分查找 - 此算法在无序列容器中无法使用(就是说要先sort一下) 其实说出了二分查找需要的条件
用于查找的内容逻辑上来说是需要有序的,查找的数量只能是一个,而不是多个。
    
bool std::binary_search(begin(),end(),val,less<T>()) 默认函数对象升序

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

#include<functional>
/*
    查找相邻的元素
    iterator adjacent_find(begin(),end());

    iterator adjacent_find(begin(),end(),func);

    二分查找
    bool binary_search -二分查找算法首先要在有序的容器中使用,在无序的容器中要先使用sort排序

*/

class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    

    //默认用的是std::less<T>()函数对象
    bool operator< (A& a) const 
        std::cout<<id_<<" "<<a.GetId()<<std::endl;
        
        return id_<a.GetId();
    

    bool operator >(A& a) const
        std::cout<<id_<<" "<<a.GetId()<<std::endl;
        
        return id_<a.GetId();
    
private:
    _Uint32t id_;
    std::string name_;
;

void Func1()
    std::vector<std::string> vec1"tom","jery","jery","rose";
    std::vector<std::string>::iterator iter1=std::adjacent_find(vec1.begin(),vec1.end());
    if(iter1!=vec1.end())
        std::cout<<*iter1<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

    std::vector<std::string> vec2"tom","jery","rose";
    auto iter2=std::adjacent_find(vec2.begin(),vec2.end());
    if(iter2!=vec2.end())
        std::cout<<*iter2<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


struct MyFind1
    bool operator()(A& a,A& b)
        return a.GetId()==b.GetId()&&a.GetName()==b.GetName();
    
;

void Func2()
    std::vector<A> vec1A(1,"tom"),A(2,"jery"),A(2,"jery");
    auto iter1=std::adjacent_find(vec1.begin(),vec1.end(),MyFind1());
    if(iter1!=vec1.end())
        std::cout<<(*iter1).GetId()<<" "<<(*iter1).GetName()<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


void Func3()
    std::vector<int> vec11,2,3,4,5,6,7,8;
    bool flag1=std::binary_search(vec1.begin(),vec1.end(),3);
    if(flag1==true)
        std::cout<<"find"<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

    std::vector<int> vec21,2,5,6,3,8,7;
    std::sort(vec2.begin(),vec2.end(),std::greater<int>());
    std::for_each(vec2.begin(),vec2.end(),[&](_Uint32t i)
        std::cout<<i<<" ";
    );
    std::cout<<std::endl;
    //默认从std::less<T>比较
    bool flag2=std::binary_search(vec2.begin(),vec2.end(),3,std::greater<int>());
    if(flag2==true)
        std::cout<<"find"<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    


//从大到小排序
struct MyFind2
    bool operator()(A a,A b)
        return a.GetId()>b.GetId();
    
;

void Func4()
    std::vector<A> vec1A(1,"tom"),A(2,"jery"),A(3,"rose");
    
    //val 为一个类,就在类里面写个函数对象
    //从小到大排序
    bool flag1=std::binary_search(vec1.begin(),vec1.end(),A(1,"tom"));
    if(flag1==true)
        std::cout<<"find"<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

    bool flag2=std::binary_search(vec1.begin(),vec1.end(),A(1,"tom"),MyFind2());
    if(flag2==true)
        std::cout<<"find"<<std::endl;
    else
        std::cout<<"not find"<<std::endl;
    

int main()
    Func1();
    Func2();
    Func3();
    Func4();
    return 0;

59、STL六大组件之统计算法

/*
    统计val出现的次数
    int std::count(begin(),end(),val)

    int std::count(begin(),end(),func)
*/

代码如下:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

#include<functional>
/*
    统计val出现的次数
    int std::count(begin(),end(),val)

    int std::count(begin(),end(),func)
*/
class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    

    //bool operator==(const A& a)
    //    return (id_==a.GetId()&&name_==a.GetName());
    //
    bool operator==(const A& a) 
        return id_ == a.id_ && name_ == a.name_;
    
//private:
    _Uint32t id_;
    std::string name_;
;

void Func1()
    std::vector<std::string> vec1"tom","jery","a","tom","a","b","a";
    _Uint32t num1=std::count(vec1.begin(),vec1.end(),"a");
    std::cout<<num1<<std::endl;
    _Uint32t num2=std::count(vec1.begin(),vec1.end(),"tom");
    std::cout<<num2<<std::endl;


void Func2()
    std::vector<A> vec1A(1,"aa"),A(2,"bb"),A(1,"aa"),A(1,"aa");
    _Uint32t num1=std::count(vec1.begin(),vec1.end(),A(1,"aa"));
    std::cout<<num1<<std::endl;


struct MyFind1
    bool operator()(std::string& str)
        return str=="aa";
    
;

struct MyFind2:public std::unary_function<_Uint32t,bool>
    bool operator()(int a) const
        return a==1;
    
;

void Func3()
    std::vector<std::string> vec1"aa","aa","bb","aa";
    _Uint32t num1=std::count_if(vec1.begin(),vec1.end(),MyFind1());
    std::cout<<num1<<std::endl;
    std::vector<int> vec21,1,2,2,2,2,2;
    _Uint32t num2=std::count_if(vec2.begin(),vec2.end(),std::not1(MyFind2()));
    std::cout<<num2<<std::endl;


struct MyFind3
    bool operator()(A& a) 
        return a.id_==1&&a.name_=="aa";
    
;

//编译类 模板 成员函数“bool std::binder2nd<MyFind4>::operator ()(A &) const”时
struct MyFind4:public std::binary_function<A,A,bool>
    bool operator()(const A& a,const A& b) const
        return a.id_==b.id_&&a.name_==b.name_;
    
;

void Func4()
    std::vector<A> vec1A(1,"aa"),A(2,"bb");
    _Uint32t num1=std::count_if(vec1.begin(),vec1.end(),MyFind3());
    std::cout<<num1<<std::endl;
    _Uint32t num2=std::count_if(vec1.begin(),vec1.end(),std::bind2nd(MyFind4(),A(1,"a")));
    std::cout<<num2<<std::endl;

int main()
    Func1();
    Func2();
    Func3();
    Func4();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
3
2
3
3
5
1
0
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> 

60、STL六大组件之合并算法

代码如下:

#include<iostream>

#include<algorithm>

#include<vector>
#include<string>
#include<functional>

class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    A() 
    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    
private:
    _Uint32t id_;
    std::string name_;
;

void Func1()
    std::vector<int> vec1 1,2,3,4 ;
    std::vector<int> vec2 3,4,5,6 ;
    std::vector<int> vec3;
    vec3.resize(vec1.size()+vec2.size());
    // std::merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin());
    // std::for_each(vec3.begin(),vec3.end(),[=](_Uint32t num)->void
    //     std::cout<<num<<" ";
    // );
    std::merge(vec1.begin(),vec1.end(),vec2.begin(),vec2.end(),vec3.begin(),std::less<int>());
    std::for_each(vec3.begin(),vec3.end(),[=](_Uint32t num)->void
        std::cout<<num<<" ";
    );
    std::cout<<std::endl;


struct MyFind1 
    bool operator()(A& a,  A& b) 
        return a.GetId() < b.GetId();
    
;
void Func2()
   std::vector<A> vec1 A(1,"tom"),A(2,"tom"),A(3,"tom"),A(4,"tom") ;
   std::vector<A> vec2 A(3,"tom"),A(4,"tom"),A(5,"tom"),A(6,"tom") ;
   std::vector<A> vec3;
   vec3.resize(vec1.size() + vec2.size());
   std::merge(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), vec3.begin(),MyFind1());
    for(auto start=vec3.begin();start!=vec3.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    


int main()
    Func1();
    Func2();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
1 2 3 3 4 4 5 6 
1 tom
2 tom
3 tom
3 tom
4 tom
4 tom
5 tom
6 tom
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g9oOK6yD-1671200465360)(C:\\Users\\hp\\AppData\\Roaming\\Typora\\typora-user-images\\image-20221215192445402.png)]

61、随机数(rand)和随机数种子(srand)的理解

实际开发应用时,我们代码中有可能会使用到随机数。所以今天来看看随机数是怎么生成的。

  • 首先rand函数可以用来产生一个数,它具备这种功能。

    • rand相关的头文件为#include<stdlib.h>
    • rand()的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定的范围里可看成是随机的。rand()返回一随机数值的范围在0至RAND_MAX 间。RAND_MAX的范围最少是在32767之间(int),用unsigned int 双字节是65535,四字节是4294967295的整数范围。0~RAND_MAX每个数字被选中的机率是相同的。用户未设定随机数种子时,系统默认的随机数种子为1。rand()产生的是伪随机数字,每次执行时是相同的,若要不同,用函数srand()初始化它。
  • srand函数用来播种随机种子,能够产生一个随机数。(播下种子seed,它啥样大家都不知道)

    srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,通常可以利用time(0)的返回值或NULL来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。“相同的种子对应相同的数值”。

  • time函数是用来计算时间的秒数的

    此函数会返回从公元 1970 年1 月1 日的UTC 时间从0 时0 分0 秒算起到现在所经过的秒数。如果t 并非空指针的话,此函数也会将返回值存到t 指针所指的内存。

获取随机数的代码如下:

srand((unsigned int)time(NULL))
for(int i=0;i<10;i++)
	//产生0到9之间的随机数
	std::cout<<rand()%10<<" ";

注意:

  • 这里的NULL还可以使用0。类型我们一般都是获取无符号整形,这个获取的随机数也只能是整数。

  • srand函数不可以放入循环内部,否则(1s以内)产生的一直都是一个数(每一秒都会产生一个随机数)。

当然你如果非要这么做,也可以在里面加个延迟函数sleep(1);但是我觉得大可不必搞这么复杂,所以上面的代码是最容易实现随机数的了。

62、STL六大组件之随机算法(洗牌算法)

/*
    洗牌算法 打乱容器中数据顺序

    void random_shuffle(begin(),end())

    void shuffle(begin(),end(),func)
*/

代码如下:

#include<iostream>
//#include<stdlib.h>
#include<time.h>
#include<vector>
#include<string>
#include<algorithm>

#include<random>
/*
    洗牌算法 打乱容器中数据顺序

    void random_shuffle(begin(),end())

    void shuffle(begin(),end(),func)
*/

class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    _Uint32t GetId()
        return id_;
    
    std::string GetName()
        return name_;
    
private:
    _Uint32t id_;
    std::string name_;
;

struct MyRand
    int operator()(int i)
        return rand()%i;
    
;

void Func1()
    srand((unsigned int)time(NULL));  //随机数种子,无符号整数,用时间来作为随机数种子
    std::vector<std::string> vec1"aa","bb","cc","dd";
    std::random_shuffle(vec1.begin(),vec1.end(),MyRand());
    std::for_each(vec1.begin(),vec1.end(),[=](std::string& str)->void
        std::cout<<str<<" ";
    );
    std::cout<<std::endl;
    std::cout<<std::endl;

    std::random_device rd;
    std::shuffle(vec1.begin(),vec1.end(),std::default_random_engine(rd()));
    std::for_each(vec1.begin(),vec1.end(),[=](std::string& str)->void
        std::cout<<str<<" ";
    );
    std::cout<<std::endl;
    std::cout<<std::endl;


void Func2()
    std::vector<A> vec1A(1,"aa"),A(2,"bb"),A(3,"cc");
    std::random_shuffle(vec1.begin(),vec1.end(),MyRand());
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    
    std::cout<<std::endl;

    std::random_device rd;
    std::shuffle(vec1.begin(),vec1.end(),std::default_random_engine(rd()));
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    
    std::cout<<std::endl;

int main()
    Func1();
    Func2();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
aa dd bb cc 

aa bb dd cc

1 aa
2 bb
3 cc

3 cc
1 aa
2 bb

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug>

63、STL六大组件之排序算法和反转算法

/*
    void sort(begin(),end(),func)

    void reverse(begin(),end())
*/


//    not1 是构造一个与谓词结果相反的一元函数对象
//    not2 是构造一个与谓词结果相反的二元函数对象
//    二元谓词 ,谓词,bool类型的函数对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKJ7Puzk-1671200465361)(C:\\Users\\hp\\AppData\\Roaming\\Typora\\typora-user-images\\image-20221216131400415.png)]

代码如下:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>

#include<functional>
/*
    void sort(begin(),end(),func)

    void reverse(begin(),end())
*/

class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    

    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    
private:
    _Uint32t id_;
    std::string name_;
;

struct MySort1
    void operator()(_Uint32t num)
        std::cout<<num<<" ";
    
;
void Func1()
    std::vector<int> vec11,3,5,2,4,6;
    std::sort(vec1.begin(),vec1.end());
    std::for_each(vec1.begin(),vec1.end(),[&](_Uint32t num)->void
        std::cout<<num<<" ";
    );
    std::cout<<std::endl;
    std::sort(vec1.begin(),vec1.end(),std::greater<int>());
    std::for_each(vec1.begin(),vec1.end(),MySort1());
    std::cout<<std::endl;


struct MySort2
    bool operator()(A& a,A& b)
        return a.GetId()>b.GetId();
    
;

//    not1 是构造一个与谓词结果相反的一元函数对象
//    not2 是构造一个与谓词结果相反的二元函数对象
//    二元谓词 ,谓词,bool类型的函数对象
struct MySort3:public std::binary_function<A,A,bool>
    bool operator()(A a,A b) const
        return a.GetId()>b.GetId();
    
;

void Func2()
    std::vector<A> vec1
        A(1,"1"),
        A(11,"11"),
        A(111,"111"),
        A(2,"2"),
        A(22,"22"),
        A(333,"333")
    ;
    std::sort(vec1.begin(),vec1.end(),MySort2());
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    

    std::sort(vec1.begin(),vec1.end(),std::not2(MySort3()));
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    
    std::cout<<std::endl<<std::endl;


void Func3()
    std::vector<int> vec11,3,5,2,4,6;
    std::reverse(vec1.begin(),vec1.end());
    std::for_each(vec1.begin(),vec1.end(),[&](_Uint32t num)->void
        std::cout<<num<<" ";
    );
    std::cout<<std::endl<<std::endl;


void Func4()
    std::vector<A> vec1
        A(1,"1"),
        A(11,"11"),
        A(111,"111"),
        A(2,"2"),
        A(22,"22"),
        A(333,"333")
    ;

    std::sort(vec1.begin(),vec1.end(),MySort2());
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    
    std::reverse(vec1.begin(),vec1.end());
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    


int main()
    Func1();
    Func2();
    Func3();
    Func4();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
1 2 3 4 5 6 
6 5 4 3 2 1
333 333
111 111
22 22
11 11
2 2
1 1
1 1
2 2
11 11
22 22
111 111
333 333


6 4 2 5 3 1

333 333
111 111
22 22
11 11
2 2
1 1
1 1
2 2
11 11
22 22
111 111
333 333
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> 

64、STL六大组件之拷贝算法和替换算法

/*
    将begin()1和end()1中的容器的元素拷贝到另一个容器2中,
    从begin()2开始填充,目标容器使用前要先开辟空间

    iterator copy(begin()1,end()1,begin()2)

    将begin()和end()范围内等于oldVal的元素替换成newVal
    
    void replace(begin(),end(),oldVal,newVal)

    将begin(),end()范围内符合func条件的元素,替换成newVal

    void replace_if(begin(),end(),func,newVal)

    将begin()1,end()1范围内的元素cp到容器2中,从begin()2处开始填充,当原容器中的元素
    等于oldVal时,目标容器中的用newVal替换,目标容器使用前要先确定空间
    iterator replace_copy(begin()1,end()1,begin()2,oldVal,newVal)

    将begin()1,end()1范围中的元素cp到容器2中,从begin()2开始填充,当原容器中的元素
    符合条件func时,用目标容器中的newVal替换,目标容器使用前要先确定空间
    iterator replace_copy_if(begin()1,end()1,func,newVal)

    交换元素
    void swap(v1,v2)
*/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPnGJtF4-1671200465362)(C:\\Users\\hp\\AppData\\Roaming\\Typora\\typora-user-images\\image-20221216150032320.png)]

代码如下:

#include<iostream>

#include<vector>
#include<string>

#include<algorithm>
#include<functional>
/*
    将begin()1和end()1中的容器的元素拷贝到另一个容器2中,
    从begin()2开始填充,目标容器使用前要先开辟空间

    iterator copy(begin()1,end()1,begin()2)

    将begin()和end()范围内等于oldVal的元素替换成newVal
    
    void replace(begin(),end(),oldVal,newVal)

    将begin(),end()范围内符合func条件的元素,替换成newVal

    void replace_if(begin(),end(),func,newVal)

    将begin()1,end()1范围内的元素cp到容器2中,从begin()2处开始填充,当原容器中的元素
    等于oldVal时,目标容器中的用newVal替换,目标容器使用前要先确定空间
    iterator replace_copy(begin()1,end()1,begin()2,oldVal,newVal)

    将begin()1,end()1范围中的元素cp到容器2中,从begin()2开始填充,当原容器中的元素
    符合条件func时,用目标容器中的newVal替换,目标容器使用前要先确定空间
    iterator replace_copy_if(begin()1,end()1,func,newVal)

    交换元素
    void swap(v1,v2)
*/
class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    

    A()
    _Uint32t GetId()
        return id_;
    

    std::string& GetName()
        return name_;
    

    bool operator==(const A& a)
        return this->id_==a.id_&&this->name_==a.name_;
    
// private:
    _Uint32t id_;
    std::string name_;
;

void Func1()
    std::vector<int> vec11,3,5,2,4,6;
    std::vector<int> vec2;
    vec2.resize(vec1.size());
    auto iter1=std::copy(vec1.begin(),vec1.end(),vec2.begin());
    for(auto iter1=vec2.begin();iter1!=vec2.end();iter1++)
        std::cout<<(*iter1)<<" ";
    
    std::cout<<std::endl<<std::endl;


void Func2()
    std::vector<A> vec1
        A(1,"1")
        ,A(11,"11")
        ,A(111,"111")
    ;
    std::vector<A> vec2;
    vec2.resize(vec1.size());
    auto iter1=std::copy(vec1.begin(),vec1.end(),vec2.begin());
    for(auto iter1=vec2.begin();iter1!=vec2.end();iter1++)
        std::cout<<(*iter1).GetId()<<" "<<(*iter1).GetName()<<std::endl;
    
    std::cout<<std::endl;


void Func3()
    std::vector<int> vec11,3,5,2,4,6;
    std::for_each(vec1.begin(),vec1.end(),[=](_Uint32t num)->void
        std::cout<<num<<" ";
    );
    std::cout<<std::endl;

    std::replace(vec1.begin(),vec1.end(),1,100);
    std::for_each(vec1.begin(),vec1.end(),[&](_Uint32t id)->void
        std::cout<<id<<" ";
    );
    std::cout<<std::endl<<std::endl;


void Func4()
    std::vector<A> vec1
        A(1,"1")
        ,A(11,"11")
        ,A(111,"111")
    ;
    std::replace(vec1.begin(),vec1.end(),A(11,"11"),A(1111,"1111"));
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).id_<<" "<<(*start).name_<<std::endl;
    


struct MyReplace1
    bool operator()(const int a)
        return a==1;
    
;

struct MyReplace2:public std::binary_function<int,int,bool>
    bool operator()(_Uint32t a,_Uint32t b) const
        return a==b;
    
;

void Func5()
    std::vector<int> vec11,3,5,2,4,6;
    std::replace_if(vec1.begin(),vec1.end(),MyReplace1(),100);
    std::for_each(vec1.begin(),vec1.end(),[=](_Uint32t id)->void
        std::cout<<id<<" ";
    );
    std::cout<<std::endl;
    std::replace_if(vec1.begin(),vec1.end(),std::bind2nd(MyReplace2(),5),50);
    std::for_each(vec1.begin(),vec1.end(),[=](_Uint32t id)->void
        std::cout<<id<<" ";
    );
    std::cout<<std::endl;

    std::cout<<std::endl<<std::endl;


void Func6()
    std::vector<int> vec11,3,5;
    std::vector<int> vec22,4,6;
    
    auto start1=vec1.begin();
    auto end1=vec1.end();
    auto start2=vec2.begin();
    auto end2=vec2.end();
    printf("%p %d\\n",start1,*start1);
    printf("%p %d\\n",start2,*start2);
    // printf("%p %d\\n",end1,*end1);
    // printf("%p %d\\n",end2,*end2);
    std::swap(vec1,vec2);

    auto start3=vec1.begin();
    auto start4=vec2.begin();
    auto end3=vec1.end();
    auto end4=vec2.end();
    printf("%p %d\\n",start3,*start3);
    printf("%p %d\\n",start4,*start4);  
    // printf("%p %d\\n",end3,*end3);
    // printf("%p %d\\n",end4,*end4); 

int main()
    Func1();
    Func2();
    Func3();
    Func4();
    Func5();

    Func6();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
1 3 5 2 4 6 

1 1
11 11
111 111

1 3 5 2 4 6
100 3 5 2 4 6

1 1
1111 1111
111 111
100 3 5 2 4 6
100 3 50 2 4 6


000000CFE5B7F6A0 1
000000CFE5B7F6C0 2
000000CFE5B7F6E0 2
000000CFE5B7F700 1
PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug>

65、STL六大组件之算术生成算法和填充算法

/*
    算术生成算法
    #include<numberic>

    T accumulate(begin(),end(),val,func)

    template<class T>T plus<T>() 加法
    template<class T>T minus<T>()减法
    template<class T>T multiplies<T> 乘法
    template<class T>T divides<T> 除法
    template<class T>T modules<T> 取模
    template<class T>T negate<T> 取反

    填充算法,容器使用前要先分配空间
    void fill(begin(),end(),val)

*/

代码如下:

#include<iostream>

#include<algorithm>

#include<vector>
#include<string>
#include<numeric>
/*
    算术生成算法
    #include<numberic>

    T accumulate(begin(),end(),val,func)

    template<class T>T plus<T>() 加法
    template<class T>T minus<T>()减法
    template<class T>T multiplies<T> 乘法
    template<class T>T divides<T> 除法
    template<class T>T modules<T> 取模
    template<class T>T negate<T> 取反

    填充算法,容器使用前要先分配空间
    void fill(begin(),end(),val)

*/

class A
public:
    A(_Uint32t id,std::string name)
    :id_(id)
    ,name_(name)
    
    A()
    _Uint32t GetId()
        return id_;
    
    std::string& GetName()
        return name_;
    
private:
    _Uint32t id_;
    std::string name_;
;

void Func1()
    std::vector<int> vec11,3,5,2,4,6;
    //std::accumulate()默认是加法
    auto iter1=std::accumulate(vec1.begin(),vec1.end(),0);  //0+1+3+5+2+4+6
    std::cout<<iter1<<std::endl;
    auto iter2=std::accumulate(vec1.begin(),vec1.end(),10); //10+1+3+5+2+4+6
    std::cout<<iter2<<std::endl;

    auto iter3=std::accumulate(vec1.begin(),vec1.end(),0,std::minus<int>()); //0-1-3-5-2-4-6
    std::cout<<iter3<<std::endl;


struct MyPlus
    _Uint32t operator()(_Uint32t num,A a)
        return num+a.GetId();
    
;

void Func2()
    std::vector<A> vec1
        A(1,"1")
        ,A(11,"11")
        ,A(111,"111")
    ;
    auto iter1=std::accumulate(vec1.begin(),vec1.end(),0,MyPlus());
    std::cout<<iter1<<std::endl;


void Func3()
    std::vector<int> vec1;
    vec1.resize(10);
    std::for_each(vec1.begin(),vec1.end(),[=](_Uint32t num)->void
        std::cout<<num<<" ";
    );
    std::cout<<std::endl;
    std::fill(vec1.begin(),vec1.end(),100);
    std::for_each(vec1.begin(),vec1.end(),[=](_Uint32t num)->void
        std::cout<<num<<" ";
    );
    std::cout<<std::endl;


void Func4()
    std::vector<A> vec1;
    vec1.resize(3);
    for(auto start=vec1.begin();start!=vec1.end();start++)
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    
    std::cout<<std::endl;
    std::fill(vec1.begin(),vec1.end(),A(1,"1"));
    for(auto start=vec1.begin();start!=vec1.end();start++)   
        std::cout<<(*start).GetId()<<" "<<(*start).GetName()<<std::endl;
    
    std::cout<<std::endl;


int main()
    Func1();
    Func2();
    Func3();
    Func4();
    return 0;

输出结果:

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug> .\\main.exe
21
31
-21
123
0 0 0 0 0 0 0 0 0 0
100 100 100 100 100 100 100 100 100 100
3452816845
3452816845
3452816845

1 1
1 1
1 1

PS D:\\C++泛型编程与模板代码\\build\\bin\\Debug>

66、STL六大组件之集合算法

/*
 *
 * #include<algorithm>
 *
 * begin1 源容器1 开始迭代器
 * end1 源容器1 结束迭代器
 * begin2 源容器2 开始迭代器
 * end2 源容器2 结束迭代器
 * begin3 目标容器开如迭代器
 * func 比较规则 默认 less
 *
 *
 *
 * 交集 源容器元素都必须是有序的,且排序规则要保持一致,目标容器使用前要分配空间
 * iterator set_intersection(begin1,end1,begin2,end2,begin3,func);
 *
 *
 * 并集 源容器元素都必须是有序的,且排序规则要保持一致,目标容器使用前要分配空间
 * iterator set_union(begin1,end1,begin2,end2,begin3,func);
 *
 *
 * 差集 源容器元素都必须是有序的,且排序规则要保持一致,目标容器使用前要分配空间
 * iterator set_difference(begin1,end1,begin2,end2,begin3,func);
 *
 *
 * */

代码如下:

#include <iostream>
#include<vector>
#include<functional>
#include<algorithm>
#include<numeric>
#include<string>

using namespace std;

/*
 *
 * #include<algorithm>
 *
 * begin1 源容器1 开始迭代器
 * end1 源容器1 结束迭代器
 * begin2 源容器2 开始迭代器
 * end2 源容器2 结束迭代器
 * begin3 目标容器开如迭代器
 * func 比较规则 默认 less
 *
 *
 *
 * 交集 源容器元素都必须是有序的,且排序规则要保持一致,目标容器使用前要分配空间
 * iterator set_intersection(begin1,end1,begin2,end2,begin3,func);
 *
 *
 * 并集 源容器元素都必须是有序的,且排序规则要保持一致,目标容器使用前要分配空间
 * iterator set_union(begin1,end1,begin2,end2,begin3,func);
 *
 *
 * 差集 源容器元素都必须是有序的,且排序规则要保持一致,目标容器使用前要分配空间
 * iterator set_difference(begin1,end1,begin2,end2,begin3,func);
 *
 *
 * */

class C1
public:
    C1(int id,string name)
        this->id=id;
        this->name=name;
    
    C1()

    int id;
    string name;
;


typedef struct myComp1:public binary_function<C1,C1,bool>
    bool operator()(const C1 &a,const C1 &b) const
        return a.id<b.id;
    
;

typedef struct myComp2
    bool operator()(const C1 &a,const C1 &b)
        return a.id>b.id;
    
;



void func2()
    vector<C1>v1C1(1,"1"),C1(22,"22"),C1(33,"33"),C1(444,"444"),C1(555,"555"),C1(999,"999");
    vector<C1>v2C1(4,"4"),C1(33,"33"),C1(44,"44"),C1(555,"555"),C1(8888,"888");
    vector<C1>v3;
    v3.resize(min(v1.size(),v2.size()));

    sort(v1.begin(),v1.end(), not2(myComp1()));
    sort(v2.begin(),v2.end(), not2(myComp1()));

    for(auto start = v1.begin();start != v1.end();start++)
        cout<<(*start).id<<" "<<(*start).name<<"   ";
    
    cout<<endl;

    for(auto start = v2.begin();start != v2.end();start++)
        cout<<(*start).id<<" "<<(*start).name<<"   ";
    
    cout<<endl<<endl;

    set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin(),myComp2());
    for(auto start = v3.begin();start != v3.end();start++)
        cout<<(*start).id<<" "<<(*start).name<<"   ";
    




void func1()
    vector<int>v11,4,2,5,3;
    vector<int>v29,4,7,8,6,5;
    vector<int>v3;
    v3.resize(min(v1.size(),v2.size()));

    sort(v1.begin(),v1.end());
    sort(v2.begin(),v2.end());

    set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for(auto start = v3.begin();start != v3.end();start++)
        cout<<*start<<" ";
    





int main()
    func2();
    return 0;

stl六大组件中算法模块sort为啥采用快速排序作为底层思想(代码片段)

文章目录一、面试官发问sort底层采用什么排序二、三种递归实现和非递归实现代码如下:三、快速排序的优化方法之三数取中四、快速排序的时间和空间复杂度一、面试官发问sort底层采用什么排序当你第一眼看到这道面试题是不... 查看详情

stl的六大容器之iterator----自定义范式(代码片段)

STL的iterator组件,分离了容器和算法。一.规定在STL体系下定义iterator,要满足规定的一些规范:1.iterator_category有5中分类,决定胃具体的操作,如:++,--,!=,==等,归纳为: Input_iterator:只读,不写output_iterator:只写,不读for... 查看详情

详解c++stl六大组件,看完不懂打我...(代码片段)

STL提供了六大组件,彼此组合套用协同工作。这六大组件分别是:容器(Containers):各种数据结构,如vector、list、deque、set、map等。从实现的角度来看,容器是一种classtemplate。算法(Algorithms)... 查看详情

详解c++stl六大组件,看完不懂打我...(代码片段)

STL提供了六大组件,彼此组合套用协同工作。这六大组件分别是:容器(Containers):各种数据结构,如vector、list、deque、set、map等。从实现的角度来看,容器是一种classtemplate。算法(Algorithms)... 查看详情

stl六大组件与底层原理(代码片段)

文章目录标准模板库STL容器1、顺序容器I.vectorII.listIII.deque2、关联容器I.map/setII.multimap/multisetIII.unordered_map/unordered_set3、容器适配器I.stackII.queueIII.priority_queue容器迭代器失效问题空间配置器1、空间配置器原理I.第一级II.第二级2、... 查看详情

stl六大组件与底层原理(代码片段)

文章目录标准模板库STL容器1、顺序容器I.vectorII.listIII.deque2、关联容器I.map/setII.multimap/multisetIII.unordered_map/unordered_set3、容器适配器I.stackII.queueIII.priority_queue容器迭代器失效问题空间配置器1、空间配置器原理I.第一级II.第二级2、... 查看详情

stl标准模板库知识点总结(代码片段)

...互操作性(相互合作性,interoperability),诞生了STL。STL提供了六大组件,彼此之间可以组合套用,这六大组件分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。容器:各种数据结构,如vector、list、deque、set、map... 查看详情

stl源码剖析(代码片段)

...(Functors):类似于函数,可以作为Algorithms的一种策略。六大组件的关系Containers通过Allocators取得数据存储空间,Algorithms通过Iterators存取Containers内容,Functors可以协助Algorithms完成不同的策略变,Adapte 查看详情

stl知识点总结(代码片段)

一、STL有哪些组件STL提供六大组件,彼此可以组合套用:1、容器容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种classtemplate。2、算法各种常见算法,如sort,search,copy,erase... 查看详情

stl第一篇初识stl(代码片段)

STL什么是STLSTL组成--六大组件组件一:容器容器分类组件二:空间配置器(alloctor)组件三--算法组件4--迭代器什么是迭代器常见的迭代器组件五---仿函数另名:函数对象什么是仿函数仿函数的示例组件六----配接器(... 查看详情

《stl源码剖析》相关面试题总结(代码片段)

一、STL简介STL提供六大组件,彼此可以组合套用:容器容器就是各种数据结构,我就不多说,看看下面这张图回忆一下就好了,从实现角度看,STL容器是一种classtemplate。算法各种常见算法,如sort,search,copy,erase等,我觉得其... 查看详情

acm常用stl容器(代码片段)

...模板库),由三大部分组成:容器,算法,迭代器234//STL六大组件:container(容器),algorthm(算法),iterator(迭代器)5//functionobject(仿函数),adaptor(适配器),allocator(空间适配器)67//STL容器89//vector10//deque(双端数组)11//stack12//queue13//list(链表... 查看详情

c++标准容器库与泛型编程(代码片段)

文章目录STL六大组件容器分类Hash与红黑树的区别分配器(allocator)STL设计模式OOP和GP模板特化malloc分配内存的一点东西容器listIterator遵循原则vectordeque红黑树容器set和multiset容器map和multimaphashtable(哈希表)迭代器的分类算法... 查看详情

c++标准容器库与泛型编程(代码片段)

文章目录STL六大组件容器分类Hash与红黑树的区别分配器(allocator)STL设计模式OOP和GP模板特化malloc分配内存的一点东西容器listIterator遵循原则vectordeque红黑树容器set和multiset容器map和multimaphashtable(哈希表)迭代器的分类算法... 查看详情

c++stl之string类的使用和实现(代码片段)

文章目录STL简介什么是STLSTL的版本STL的六大组件STL的重要性string为什么学习string类?C语言中的字符串标准库中的string类string类string类对象的构造函数string类的成员函数的使用string类的模拟实现经典的string类问题浅拷贝深拷贝... 查看详情

c++之stl

...rator) 容器和算法之间通过迭代器进行无缝连接 STL六大组件容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器1、容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据2、算法:各种常用算法,... 查看详情

(c++基础_stl)——初识stl(代码片段)

...绍1STL基本认识1.1STL的诞生与发展1.2STL的基础概念1.3STL的六大组件1.4STL中容器、算法、迭代器的概括1.5Vector容器基本使用个人格言(C++基础_STL)——初识STL    在日常的C++开发过程中,我们会经常使用到STL最为... 查看详情

(c++基础_stl)——初识stl(代码片段)

...绍1STL基本认识1.1STL的诞生与发展1.2STL的基础概念1.3STL的六大组件1.4STL中容器、算法、迭代器的概括1.5Vector容器基本使用个人格言(C++基础_STL)——初识STL    在日常的C++开发过程中,我们会经常使用到STL最为... 查看详情