大话STL第十期终章——算法

发布于:2022-12-21 ⋅ 阅读:(209) ⋅ 点赞:(0)

这一期就是我们STL基本学习的最后一期了~~完结撒花~

前期系列内容回顾:

大话STL第一期——初识相见恨晚
大话STL第二期——机械先驱—vector
大话STL第三期——deque(双端动态数组
大话STL第四期——list双向链表
大话STL第五期——set/multiset(含pair对组)
大话STL第六期——map/multimap
大话STL第七期——stack栈
大话STL第八期——queue队列
大话STL第九期——仿函数(函数对象)

关注主页不迷路:Oorik的博客_CSDN博客-C,C++领域博主 

 文章篇幅较长,我会根据功能分类进行演示和总结,可以跳转自己需要的地方

文章目录

STL常用算法概述:

常用遍历算法:

for_each:遍历容器元素

transform:搬用容器到另一个容器中

常用查找算法:

find:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

find_if:按条件查找元素

adjacent_find:查找相邻重复元素,返回相邻元素的第一个位置的迭代器

binary_search:查找指定元素是否存在,查到返回true,否则返回false

count:统计元素个数

count_if:按条件统计元素个数

常用排序算法:

sort:对容器内部进行排序

random_shuffle:洗牌打乱顺序,指定范围内的元素随机调整次序

merge:两个容器元素合并,并存储到另一个容器中

reverse:将容器内元素进行反转

常用的拷贝和替换算法:

copy:容器内指定元素拷贝到另一容器

replace:将容器指定范围内的旧元素修改为新元素

replace-if:将区间内满足条件的元素,替换成指定元素

swap:互换两个同种类型容器的元素

常用的算数生成算法:

accumulate(求累加):将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值

fill:对容器实现指定元素的填充

常用的集合算法:

set_intersection:求两个集合的交集,源容器必须有序,目标容器开辟取两个源容器较小的

set_union:求两个集合的并集,源容器必须有序,目标容器开辟取两个源容器之和

set_difference:求两个集合的差集,源容器必须有序,目标容器开辟取两个源容器较大的


STL常用算法概述:

  1. 算法主要是由头文件<algorithm> <functional> <numeric>组成

  2. <algorithm>是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历、赋值、修改等等

  3. <functional> 定义了一些模板类。用以声明函数对象

  4. <numeric>体积很小,只包括几个在序列上面进行简单教学运算的模板函数

常用遍历算法:

for_each:遍历容器元素

函数原型:for_each(iterator beg,iterator end, _func);

beg开始迭代器

end结束迭代器

_func函数或者函数对象

void show(string a)//利用函数
{
    cout << a << " " << endl;
}
class A {             //利用函数对象
public:
    void operator ()(string a)
    {
        cout << a << " " << endl;
    }
};
int main()
{
    vector<string> vv{ "OK","张三","李四" };
    for_each(vv.begin(), vv.end(), show);
    cout << "---------------" << endl;
    for_each(vv.begin(), vv.end(),A());
    return 0;
}

transform:搬用容器到另一个容器中

函数原型:for_each(iterator beg1,iterator end1,interator beg2 ,_func);

beg1源开始迭代器

end1源结束迭代器

beg2目标容器开始迭代器

_func函数或者函数对象 

void show(int a)
{
    cout << a << " " << endl;
}
class TT{
public:
    int operator ()(int a)
    {
        return a;
    }
};

int ok(int a)
{
    return a + 100;
}

int main()
{
    vector<int> vv;//源容器
    for (int i = 0; i < 10; ++i)
    {
        vv.push_back(i + 1);
    }
    vector<int> vg;//目标容器 这样构造没有容量
    vg.resize(vv.size());//目标容器需要开辟空间

    //正常的搬运   利用函数对象方式
    transform(vv.begin(), vv.end(), vg.begin(), TT());
    for_each(vg.begin(), vg.end(), show);
    cout << "------------------------" << endl;
    //边搬运边计算,因此要重写相对应的逻辑函数或者函数对象
    transform(vv.begin(), vv.end(), vg.begin(), ok);//利用函数
    for_each(vg.begin(), vg.end(), show);
    return 0;
}

常用查找算法:

find:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

函数原型:find(iterator beg,iterator end,value);

beg开始迭代器

end结束迭代器

value所要查找的元素

class TT{
private:
   
    string name;
    int age;
public:
    TT(string name, int age) :name(name), age(age) {

    }
    string Getname(){
        return this->name;
    }
    int Getage() {
        return this->age;
    }
    //重载== 让底层find如何对比自定义数据类型
    bool operator==(const TT& t)
    {
        if (this->name == t.name && this->age == t.age)
        {
            return true;
        }
        else
            return false;
    }
};


int main()
{
    vector<TT> vv{ {"aa",3},{"bb",4},{"cc",5} };
    TT pp("cc", 5);
    auto it = find(vv.begin(), vv.end(),pp);
    if (it == vv.end())
    {
        cout << "没有找到" << endl;
    }
    else
        cout << "找到了" << it->Getname()<<" "<<it->Getage()<<endl; 
    return 0;
}

find_if:按条件查找元素

函数原型:find(iterator beg,iterator end,pred);

beg开始迭代器

end结束迭代器

pred函数或者谓词(返回bool类型的仿函数)

class TT{
private:
    string name;
    int age;
public:
    TT(string name, int age) :name(name), age(age) {

    }
    string Getname()const{
        return this->name;
    }
    int Getage()const {
        return this->age;
    }
};
//函数对象找age大于3的人
class AA {
public:
    bool operator()( const TT& t)
    {
        if (t.Getage() > 3)
        {
            return true;
        }
        else
            return false;
    }
};
int main()
{
    vector<TT> vv{ {"aa",3},{"bb",4},{"cc",5} };
    auto it = find_if(vv.begin(), vv.end(),AA());
   for(;it != vv.end();it++)
    {
         if(it == vv.end())
    {
        cout << "没有找到" << endl;
    }
          else
        cout << "找到了" << it->Getname()<<" "<<it->Getage()<<endl;
    }
    return 0;
}

adjacent_find:查找相邻重复元素,返回相邻元素的第一个位置的迭代器

函数原型:adjacent_find(interator beg,interator end)

beg开始迭代器

end结束迭代器

int main()
{
    vector<int> vv{1,2,3,4,5,5,6 };
    auto it = adjacent_find(vv.begin(), vv.end());
   if(it == vv.end())
    {
        cout << "没有找到" << endl;
    }
          else
        cout << "找到了" <<*it<<endl;
  

    return 0;
}

binary_search:查找指定元素是否存在,查到返回true,否则返回false

函数原型:bool binary_serach(interator beg,interator end,value)

注意:在无序序列中不可用

beg开始迭代器

end结束迭代器

value所要查找的元素

int main()
{
    vector<int> vv{1,2,3,4,5,5,6 };
    if (binary_search(vv.begin(), vv.end(), 7) == 1)
        cout << "找到了" << endl;
    else
        cout << "没有找到" << endl;
 
    return 0;
}

count:统计元素个数

函数原型:count(interator beg,interator end,value)

beg开始迭代器

end结束迭代器

value所要查找的元素

class TT {
public:
    string name;
    int age;
    TT(string name, int age) :name(name), age(age) {
    }
    bool operator==(const TT& t)
    {
        if (name == t.name && age == t.age)
        {
            return true;
        }
        else
            return false;
    }//统计自定义数据类型时候需要配合重载的operator==
};
int main()
{
    vector<int> vv{1,2,3,4,5,5,6 };
    int n = count(vv.begin(), vv.end(), 5);//统计5出现的次数
    cout << n << endl;

    vector<TT> vm{ {"刘备",3},{"张飞",4} };
    TT t1{ "张飞",4 };
    int m = count(vm.begin(), vm.end(), t1);
    cout << m << endl;

    return 0;
}

count_if:按条件统计元素个数

函数原型:count_if(interator beg,interator end,pred)

beg开始迭代器

end结束迭代器

pred条件谓词(bool仿函数)
class TT {
public:
    string name;
    int age;
    TT(string name, int age) :name(name), age(age) {
    }
  
};
class AA {
public:
    bool operator()(const TT& t)
    {
        if (t.age > 1)//统计年龄大于1的
            return true;
        else
            return false;
    }
};
class BB {
public:
    bool operator()(int b)
    {
        return b > 2;
    }
};

int main()
{
    vector<int> vv{1,2,3,4,5,5,6 };
    int n = count_if(vv.begin(), vv.end(), BB());//统计大于2的个数
    cout << n << endl;

    vector<TT> vm{ {"刘备",3},{"张飞",4} };  
    int m = count_if(vm.begin(), vm.end(), AA());//统计年龄大于1的
    cout << "年龄大于1的人有:" << m <<endl;
    return 0;
}

常用排序算法:

sort:对容器内部进行排序

函数原型:sort(interator beg,interator end,pred)

beg开始迭代器

end结束迭代器

pred条件谓词(bool仿函数)

void mprint(int a)
{
    cout << a << " ";
}
int main()
{
    vector<int> vv{1,3,10,11,2,4,5,3,4,5,4 };
    sort(vv.begin(), vv.end());//默认升序
    for (int i = 0; i < vv.size(); ++i)
    {
        cout << vv[i] << " ";
    }
    cout << endl;
    //改为升序,利用STL内置的仿函数
    sort(vv.begin(), vv.end(),greater<>());
    //利用for_each打印
    for_each(vv.begin(), vv.end(), mprint);
    return 0;
}

random_shuffle:洗牌打乱顺序,指定范围内的元素随机调整次序

函数原型:random_shuffle(interator beg,interator end)

beg开始迭代器

end结束迭代器

void mprint(int a)
{
    cout << a << " ";
}
int main()
{
    srand((unsigned int)time(NULL));
    vector<int> vv{1,2,3,4,5,6,7,8 };
    //利用洗牌算法打乱顺序,但是每次打乱结果都是一样的
    //如果需要真的随机,那就需要添加随机种子
    random_shuffle(vv.begin(), vv.end());
 
    for_each(vv.begin(), vv.end(), mprint);
    return 0;
}

merge:两个容器元素合并,并存储到另一个容器中

注意:两个容器必须是有序的,且合并之后同样有序

函数原型:merge(interator beg1,interator end1,interator beg2,interator end2,interator dest)

beg1 容器1开始迭代器

end1 容器1结束迭代器

beg2 容器2开始迭代器

end2 容器2结束迭代器

dest 目标容器开始迭代器

void mprint(int a)
{
    cout << a << " ";
}
int main()
{
   
    vector<int> vv{1,2,3,4,5,6,7,8 };//源容器1
    vector<int> vm{ 2,4,5,8 ,10,14,25};//源容器2

    vector<int> vx;//目标容器
    vx.resize(vv.size() + vm.size());//分配空间

    merge(vv.begin(), vv.end(), vm.begin(), vm.end(), vx.begin());
    for_each(vx.begin(), vx.end(), mprint);
    return 0;
}

reverse:将容器内元素进行反转

函数原型:reverse(interator beg,interator end)

beg开始迭代器

end结束迭代器

void mprint(int a)
{
    cout << a << " ";
}
int main()
{
   
    vector<int> vv{1,2,3,4,5,6,7,8 };//源容器1
    cout << "反转前:" << endl;
    for_each(vv.begin(), vv.end(), mprint);
    cout << endl;


    cout << "反转后:" << endl;
    reverse(vv.begin(), vv.end());
    for_each(vv.begin(), vv.end(), mprint);
    return 0;
}

常用的拷贝和替换算法:

copy:容器内指定元素拷贝到另一容器

函数原型:copy(interator beg,interator end,interator dest)

beg源容器开始迭代器

end源容器结束迭代器

dest目标容器开始拷贝位置的迭代器

void mprint(int a)
{
    cout << a << " ";
}
int main()
{
    
    vector<int> vv{1,2,3,4,5,6,7,8 };//源容器
    
    vector<int>vx(15, 2);//目标容器
    //开辟了15 个2 ,源容器元素少拷贝到目标容器后
    //前面的元素改变,后面依然是2
    //如果目标容器容量小或者没有,需要申请容量

    copy(vv.begin(), vv.end(), vx.begin());
    
    for_each(vx.begin(), vx.end(), mprint);
    return 0;
}

replace:将容器指定范围内的旧元素修改为新元素

replace(interator beg,interator end,oldvalue,newvalue)

beg开始迭代器

end结束迭代器

oldvalue旧元素

newvalue新元素

int main()
{
    
    vector<int> vv{1,2,5,5,4,5,5,6,7,8 };
    
    replace(vv.begin() + 2, vv.end(), 5, 50);
    //将2下标到end区间的5都换成50  ,begin和end是左闭右开的区间
    for (auto it = vv.begin(); it != vv.end(); it++)
    {
        cout << (*it) << " ";

    }

    return 0;
}

replace-if:将区间内满足条件的元素,替换成指定元素

replace_if(interator beg,interator end,pred,newvalue)

beg开始迭代器

end结束迭代器

pred 谓词

newvalue替换的新元素

class Pred { //仿函数
public:
    bool operator()(string name)
    {
        return name == "张三";
    }
};
bool AA(string name)//普通自定义函数
{
    return name == "张三";
}
int main()
{
    
    vector<string>vv;
    vv.push_back("张三");
    vv.push_back("李四");
    vv.push_back("张三");
    vv.push_back("李四");
    vv.push_back("张三");
    
    //将张三全部替换为王五
    replace_if(vv.begin(), vv.end(), Pred(), "王五");//调用的仿函数,也可以调用普通函数AA
    for (auto it = vv.begin(); it != vv.end(); it++)
    {
        cout << (*it) << " ";
    }
    return 0;
}

swap:互换两个同种类型容器的元素

swap(container c1 ,container c2);

c1 容器

c2容器

void show(vector<int>&v1)
{
    for (auto it = v1.begin(); it != v1.end(); it++)
    {
        cout << (*it) << " ";
    }
    cout << endl;
}
int main()
{
    vector<int>v1{5,5,1,2,4,5};

    vector<int>v2{ 1,2,3,4,5,6,7,8,9,10 };

    cout << "v1交换前:" << endl;
    show(v1);
    cout << "v2交换前:" << endl;
    show(v2);

    cout << "------------------------------" << endl;

    swap(v1, v2);
   // v1.swap(v2);使用vector内置的swap交换 
    cout << "v1交换后:" << endl;
    show(v1);
    cout << "v2交换后:" << endl;
    show(v2); 
}

常用的算数生成算法:

accumulate(求累加):将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值

函数原型:accumulate(interator beg,interator end,value);

beg 开始迭代器

end 结束迭代器

value 和的起始值

int main()
{
    vector<int>vv{ 1,2,3,4,5,6,7,8,9,10 };
    int n = accumulate(vv.begin(), vv.end(),100);
    cout << n << endl;//155,因为内部起始值设置的是100
    return 0;
}

fill:对容器实现指定元素的填充

函数原型:fill(interator beg,interator end,value);

beg 开始迭代器

end 结束迭代器

value 填充的值

void show(vector<int>&v1)
{
    for (auto it = v1.begin(); it != v1.end(); it++)
    {
        cout << (*it) << " ";
    }
    cout << endl;
}
int main()
{

    vector<int>vv(10, 1);//初始化10个1
    fill(vv.begin(), vv.begin() + 5, 2);//前5个填充为2
    show(vv);
    return 0;
 
}

常用的集合算法:

set_intersection:求两个集合的交集,源容器必须有序,目标容器开辟取两个源容器较小的

函数原型:set_intersection(interator beg1,interator end1,interator beg2,interator end2,interator dest)

beg1容器1的开始迭代器

end1容器1的结束迭代器

beg2容器2的开始迭代器

end2容器2的结束迭代器

dest目标容器的开始迭代器

set_union

void show(vector<int>&v1)
{
    for (auto it = v1.begin(); it != v1.end(); it++)
    {
        cout << (*it) << " ";
    }
    cout << endl;
}
int main()
{
    vector<int>vv{ 0,1,2,3,4,5,6,7,8,9 };//容器1
    vector<int>vvm{ 6,7,8,9,10,11,12 };//容器2
    vector<int>vmx;//目标容器
    vmx.resize(min(vv.size(),vvm.size()));//开辟空间,取小容器大小
    set_intersection(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    show(vmx);//会遍历所有数据将交集数据以及后面申请空间默认的0都打印出来
                //6 7 8 9 0 0 0

    //返回交集结束的迭代器
    auto is= set_intersection(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    //输出
    for (auto im=vmx.begin();im!=is;im++)
    {
        cout << (*im) << " ";//6 7 8 9
    }
    return 0;
 
}

set_union:求两个集合的并集,源容器必须有序,目标容器开辟取两个源容器之和

函数原型:set_union(interator beg1,interator end1,interator beg2,interator end2,interator dest)

beg1容器1的开始迭代器

end1容器1的结束迭代器

beg2容器2的开始迭代器

end2容器2的结束迭代器

dest目标容器的开始迭代器

void show(vector<int>&v1)
{
    for (auto it = v1.begin(); it != v1.end(); it++)
    {
        cout << (*it) << " ";
    }
    cout << endl;
}
int main()
{
    vector<int>vv{ 1,2,3,4,4,5,6,7,7};//容器1
    vector<int>vvm{ 6,7,8,9,10,11,12 };//容器2
    vector<int>vmx;//目标容器
    vmx.resize(vv.size()+vvm.size());
    set_union(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    show(vmx);//会遍历所有数据将并集数据以及(如果空间有剩余)后面申请空间默认的0都打印出来
            
    //返回并集结束的迭代器
    auto is= set_union(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    //输出
    for (auto im=vmx.begin();im!=is;im++)
    {
        cout << (*im) << " ";
    }
    return 0;
 
}

set_difference:求两个集合的差集,源容器必须有序,目标容器开辟取两个源容器较大的

函数原型:set_difference(interator beg1,interator end1,interator beg2,interator end2,interator dest)

beg1容器1的开始迭代器

end1容器1的结束迭代器

beg2容器2的开始迭代器

end2容器2的结束迭代器

dest目标容器的开始迭代器

void show(vector<int>&v1)
{
    for (auto it = v1.begin(); it != v1.end(); it++)
    {
        cout << (*it) << " ";
    }
    cout << endl;
}
int main()
{
    vector<int>vv{ 1,2,3,4,4,5,6,7,7};//容器1
    vector<int>vvm{ 6,7,8,9,10,11,12 };//容器2
    vector<int>vmx;//目标容器
   vmx.resize(max(vv.size(),vvm.size()));//最特殊的情况取最大的
    set_difference(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    show(vmx);//会遍历所有数据将差集数据以及(如果空间有剩余)后面申请空间默认的0都打印出来
                

    //返回并集结束的迭代器
    auto is= set_difference(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    //输出
    for (auto im=vmx.begin();im!=is;im++)
    {
        cout << (*im) << " ";
    }
    return 0;
 
}

STL系列基础更新到这里就结束了,有兴趣订阅专栏,收藏学习。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到