C++ STL

目录

1、STL的基本概念:

2、常用容器:

(1)、string容器

1)、string容器存取字符的操作

2)、string的拼接操作

3)、string查找和替换

4)、字符串比较:

5)、string的字串

6)、string和c-style字符串的转换

(2)、vector容器

1)、vector中size与容量的变化规律

2)、vector构造函数

3)、赋值

4)、vector大小的操作

5)、vector插入和删除操作

6)、巧用swap收缩空间

(3)、deque容器

1)、deque容器的特性

2)、常用的API

(4)、综合案例

(5)、stack容器(栈容器)

1)、stack容器的特性

2)、常用API

(6)、queue容器(队列容器)

1)、queue容器的特性

2)、常用API

(7)、list容器(双向链表)

1)、list容器的特性

(8)、set和multiset容器

1)、set容器的特性

2)、multiset容器的特性

3)、常用API

(9)、对组

1)、对组的特性

(10)、map/multimap容器

1)、常用API

(11)、STL容器的总结:

3、算法:

(1)、仿函数(函数对象)

(2)、谓词

(3)、内建函数对象(由STL提供的函数对象)

4、适配器:

(1)、函数对象作为适配器

(2)、函数指针作为适配器

(3)、成员函数做适配器

(4)、取反适配器、

5、常用算法:

(1)、遍历算法

(2)、transform算法

(3)、find 算法 查找元素

(4)、find_if 算法 条件查找

(5)、adjacent_find 算法

(6)、binary_search 算法 二分查找法

(7)、binary_search二分法查找算法

(8)、count 算法 统计元素出现次数

(9)、count_if算法统计元素出现次数

(10)、排序算法 merge 合并

(11)、sort排序算法

(12)、random_shuffle 洗牌算法

(13)、reverse 算法 反转指定范围的元素

(14)、copy 算法 将容器内指定范围的元素拷贝到另一容器中

(15)、replace 算法 将容器内指定范围的旧元素修改为新元素

(16)、accmulate 算法 计算容器元素累计总和

(17)、fill 算法 向容器中添加元素

(18)、常用集合算法


1、STL的基本概念:

为了建立数据结构和算法的一套标准,并且降低他们之间的耦合关系,以提升各自的独立性、弹性、交互操作(相互合作性)诞生了STL。

容器:存放数据。

算法:操作数据。

迭代器:算法通过迭代器操作容器。

仿函数:为算法提供策略,如:运算符重载。

适配器:为算法提供接口。

空间配置器:为算法和容器管理内存空间。

算法分为:质变算法和非质变算法。

质变算法:指的是运算过程中会改变区间的元素的内容。例如拷贝替换删除等。

非质变算法:指的是运算过程中不会改变区间元素的内容。例如查找、计数、遍历、查找极值。

iterator(迭代器)模式定义如下:

提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器内部表示方式。

2、常用容器:

(1)、string容器

1)、string容器存取字符的操作

常用的一些操作:

构造
string();//创建一个空的字符串 例如: string str;
string(const string& str);//使用一个 string 对象初始化另一个 string 对象
string(const char* s);//使用字符串 s 初始化
string(int n, char c);//使用 n 个字符 c 初始化 v
赋值
string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串 s 赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串 s 赋给当前的字符串
string& assign(const char *s, int n);//把字符串 s 的前 n 个字符赋给当前的字符串
string& assign(const string &s);//把字符串 s 赋给当前字符串
string& assign(int n, char c);//用 n 个字符 c 赋给当前字符串
string& assign(const string &s, int start, int n);//将 s 从 start 开始 n 个字符赋值给字符串

例子:

void test02()
{
    string str = "hello world";
    cout << str[1] << "  " << str.at(1) << endl;
}

2)、string的拼接操作

常用的一些操作:

string 拼接操作
string& operator+=(const string& str);//重载+=操作符
string& operator+=(const char* str);//重载+=操作符
string& operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串 s 连接到当前字符串结尾
string& append(const char *s, int n);//把字符串 s 的前 n 个字符连接到当前字符串结尾
string& append(const string &s);//同 operator+=()
string& append(const string &s, int pos, int n);//把字符串 s 中从 pos 开始的 n 个字符连接到当前字符串结尾
string& append(int n, char c);//在当前字符串结尾添加 n 个字符 c
*/

例子: 

void test03()
{
    string str1("hello");
    string str2("world");

    str1 += str2;  //拼接、追加
    cout << str1 << endl;

    string  str3("hahaxixi");
    //从第零位开始的后面四个拼接
    str1.append(str3, 0, 4);
    cout << str1 << endl;
}

3)、string查找和替换

常用操作:


int find(const string& str, int pos = 0) const; //查找 str 第一次出现位置,
从 pos 开始查找
int find(const char* s, int pos = 0) const; //查找 s 第一次出现位置,从 po
s 开始查找
int find(const char* s, int pos, int n) const; //从 pos 位置查找 s 的前 n
个字符第一次位置
int find(const char c, int pos = 0) const; //查找字符 c 第一次出现位置
int rfind(const string& str, int pos = npos) const;//查找 str 最后一次位
置,从 pos 开始查找
int rfind(const char* s, int pos = npos) const;//查找 s 最后一次出现位置,
从 pos 开始查找
int rfind(const char* s, int pos, int n) const;//从 pos 查找 s 的前 n 个字符
最后一次位置
int rfind(const char c, int pos = 0) const; //查找字符 c 最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从 pos 开始 n 个
字符为字符串 str
string& replace(int pos, int n, const char* s); //替换从 pos 开始的 n 个字
符为字符串 s

例子:

void test04()
{
    string str1("hello world");
    string str2("world");
    //在str1中寻找str2的开头
    cout << str1.find(str2) << endl;
    //在str1中寻找最后一个l
    cout << str1.rfind('l') << endl;
}
void test05()
{
    string str("cdaberuyabodabcd");
    int pos = 0;
    while(1)
    {   //寻找ab在字符串中的位置并且返回到ret中
        int ret = str.find("ab", pos);
        if(ret < 0) break;
        //替换掉ad位**
        str.replace(ret, 2, "**");
        pos = ret + 2;
    }
    cout << str << endl;
}

4)、字符串比较:

常用操作


 string 比较操作
compare 函数在>时返回 1, <时返回 -1, ==时返回 0。
int compare(const string &s) const;//与字符串 s 比较
int compare(const char *s) const;//与字符串 s 比较

例子:

void test06()
{
    string str1("hello");
    string str2("hollo");
#if  1
    if(str1 > "hollo"){
        cout << "str1 大于 str2" << endl;
    }
    else if(str1 < "hollo"){
        cout << "str1 小于 str2" << endl;
    }
    else{
        cout << "str1 等于 str2" << endl;
    }
#endif
    if(str1.compare(str2) == 0){
        cout << "str1 等于 str2" << endl;
    }else{
        cout << "str1 不等于 str2" << endl;
    }
}

5)、string的字串

/*
string 子串
string substr(int pos = 0, int n = npos) const;//返回由 pos 开始的 n 个字符
组成的字符串
*/
void test07()
{
    string str("hello world");
    cout << str.substr(2, 5) << endl;
}

6)、string和c-style字符串的转换

*
 string 和 c-style 字符串转换
*/
void test09()
{
    //char *转string 编译器默认支持
    string str = "hello world";


    //string 转char *
    const char *p = str.c_str();
    cout << p << endl;
}

(2)、vector容器

vector容器的优点:

类模板,单端动态数组,vector容器时随机访问迭代器。

动态数组,可以自动改变大小,支持动态增加删除元素以及随机访问元素,提供面向对象的接口

1)、vector中size与容量的变化规律

oid test01()
{
    vector<int> v;
    cout << "v的size = " << v.size() << " 容量 = " << v.capacity() << endl;
    for(int i = 0; i < 1000; i++){
        v.push_back(i);
        cout << "v的size = " << v.size() << " 容量 = " << v.capacity() << endl;
    }
}

差不多可以理解为1.5倍

2)、vector构造函数


vector 构造函数
vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());//将 v(begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//构造函数将 n 个 elem 拷贝给本身。
vector(const vector &vec);//拷贝构造函数。
#include <iostream>
#include<vector>
using namespace std;
void test01()
{
    vector<int>v1(5,10);
    //vector容器,存放int型数据,初始化5个元素全部为10。

    //利用迭代器来遍历vector容器
    vector<int>::iterator it =v1.begin();
    //v1.begin()指向容器的开头,v1.end()指向容器的结尾。
    for(;it !=v1.end();it++)
    {
        cout<<*it<<" ";
        //it指针取值就是当前的数据。
    }
    cout<<endl;
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

3)、赋值

vector 常用赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
vector& operator=(const vector &vec);//重载等号操作符
swap(vec);// 将 vec 与本身的元素互换。
#include <iostream>
#include<vector>
using namespace std;
void myprintf(vector<int>&v)
{
    vector<int>::iterator it =v.begin();
    for(;it != v.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}

void test01()
{
    vector<int>v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    myprintf(v1);

    vector<int>v2;
    v2=v1;
    myprintf(v2);

    vector<int>v3;
    v3.assign(5,10);
    myprintf(v3);

    vector<int>v4;
    v4.assign(v1.begin(),v1.end());
    myprintf(v4);

    v4.swap(v3);
    myprintf(v4);
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

4)、vector大小的操作

vector 大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。
如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为 num,若容器变长(容量的大小也会发生变化),则以 elem 值填
充新位置。如果容器变短,则末尾超出容器长>度的元素被删除(但容量不会发生变化)。
capacity();//容器的容量
reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
#include <iostream>
#include<vector>
using namespace std;
void myprintf(vector<int>&v)
{
    vector<int>::iterator it =v.begin();
    for(;it != v.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}

void test01()
{
    vector<int>v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    myprintf(v1);

    if(v1.empty())
    {
        cout<<"v1为空容器"<<endl;
        return;
    }
    cout<<v1.size()<<endl;

    //v.resize()一个参数,重新定制容器大小,扩大或者缩小,缩小会丢失数据
    //俩个参数,扩大会在后面加上第二个参数。

    v1.resize(10,100);
    cout<<v1.size()<<endl;
    myprintf(v1);

    v1.resize(2);
    cout<<v1.size()<<endl;
    myprintf(v1);
    
    //reserve预留容器的容量而不是size
    vector<int>v2;
    v2.reserve(10);
    cout<<v2.capacity()<<" "<<v2.size()<<endl;

}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

5)、vector插入和删除操作

insert(const_iterator pos, int count,ele);//迭代器指向位置 pos 插入 count
个元素 ele.
push_back(ele); //尾部插入元素 ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从 start 到 end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素
#include <iostream>
#include<vector>
using namespace std;
void myprintf(vector<int>&v)
{
    vector<int>::iterator it =v.begin();
    for(;it != v.end();it++)
    {
        cout<<*it<<" ";
    }
    cout<<endl;
}

void test01()
{
    vector<int>v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    myprintf(v1);
    //pop_back从vector容器后面删除
    v1.pop_back();
    v1.pop_back();
    myprintf(v1);
    //三个参数:位置,插入的数量,插入的参数
    v1.insert(v1.begin()+1,3,100);
    myprintf(v1);
    //删除
    v1.erase(v1.begin()+1,v1.begin()+4);
    myprintf(v1);
    
    v1.clear();
    myprintf(v1);
    
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

6)、巧用swap收缩空间


void test01()
{
    vector<int>v1(5,100);
    v1.reserve(1000);

    cout<<v1.size()<<" "<<v1.capacity()<<endl;
    
    //v1得到最好的容量匹配现在的size,提高效率。
    vector<int>(v1).swap(v1);

    cout<<v1.size()<<" "<<v1.capacity()<<endl;


}

(3)、deque容器

1)、deque容器的特性

双端插入和删除的动态数组,采用随机迭代器。没用容量概念,数据由缓冲区管理

2)、常用的API

1.deque 构造函数

deque<T> deqT;//默认构造形式
deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);//构造函数将 n 个 elem 拷贝给本身。
deque(const deque &deq);//拷贝构造函数。

2.deque赋值操作

deque 赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
deque& operator=(const deque &deq); //重载等号操作符
swap(deq);// 将 deq 与本身的元素互换

3.deque大小的操作

deque 大小操作
deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
deque.resize(num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位
置。 如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为 num,若容器变长,则以 elem 值
填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。

4.deque的双端插入与删除

deque 双端插入和删除操作
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据

5.deque数据存取

deque 数据存取
at(idx);//返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range。
operator[];//返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据

6.deque插入操作

deque 插入操作
insert(pos,elem);//在 pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。

7.deque的删除操作

deque 删除操作
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。

案例:

void printDequeInt(deque<int> &d)
{
    deque<int>::iterator it = d.begin();
    for(; it != d.end(); it++)
        cout << *it << " ";
     cout << endl;
}
void test01()
{
    deque<int> d1;
    //尾部插入
    d1.push_back(10);
    d1.push_back(20);
    d1.push_back(30);
    //头部插入
    d1.push_front(40);
    d1.push_front(50);


    printDequeInt(d1);


    deque<int> d2;
    d2 = d1;
    printDequeInt(d2);
    cout << "d2的大小为:" << d2.size() << endl;
}

(4)、综合案例

有 5 名选手:选手 ABCDE,10 个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。

#include <iostream>
#include<vector>
#include<deque>
#include <algorithm>

using namespace std;
class person
{
    friend void printperson(vector<person>&v);
    friend void playgame(vector<person>&v);
private:
    string name;
    float score;
public:
    person(){}
    person(string name,float score):name(name),score(score){}
    ~person(){}
};


//无名选手的初始化名字,并且放入vector容器
void creatperson(vector<person>&v)
{
    string tmpname="ABCDE";
    for(int i =0;i<5;i++)
    {
        string name ="选手";
        name+=tmpname[i];
        v.push_back(person(name,0.0f));
    }

}
//十个评委打分放在另一个deque容器中,采用随机数方法初始化
//vector容器五个选手,每个选手有一个deque容器存放分数
#include<time.h>
void playgame(vector<person>&v)
{
    srand(time(NULL));
    vector<person>::iterator it =v.begin();
    for(;it != v.end();it++)
    {
        deque<float>d;
        for(int i =0;i<10;i++)
        {
            float score = (float)(rand()%41+60);
            d.push_back(score);
        }
        sort(d.begin(),d.end());
        d.pop_front();
        d.pop_back();
        float sum = accumulate(d.begin(),d.end(),0);
        (*it).score = sum/d.size();
    }
}
void printperson(vector<person>&v)
{
    vector<person>::iterator it = v.begin();
    for(;it != v.end();it++){
        cout<<(*it).name<<" 的成绩 "<<(*it).score<<endl;
    }
}

void test01()
{
    //创建5名选手放入vector容器中
    vector<person>v;
    creatperson(v);

    //参加比赛
    playgame(v);

    //打印选手的成绩
    printperson(v);

}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

(5)、stack容器(栈容器)

1)、stack容器的特性

先进后出。永远指向栈顶元素。只能通过栈顶元素访问栈容器。不提供遍历没用迭代器

2)、常用API

#include <iostream>
#include<stack>


using namespace std;
void test01()
{
    stack<int>s;

    s.push(10);
    s.push(20);
    s.push(30);
    s.push(40);
    s.push(50);

    cout<<s.size()<<endl;

    while(!s.empty())
    {
        cout<<s.top()<<" ";//栈顶元素
        s.pop();//出栈
    }
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

(6)、queue容器(队列容器)

1)、queue容器的特性

先进先出,有俩个口,一个入口,一个出口,没有迭代器不支持遍历

2)、常用API

#include <iostream>
#include<queue>


using namespace std;
void test01()
{
   queue<int>q;

    q.push(10);
    q.push(20);
    q.push(30);
    q.push(40);
    q.push(50);

    cout<<q.size()<<endl;

    while(!q.empty())
    {
        cout<<q.front()<<" ";//栈顶元素
        q.pop();//出栈
    }
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

(7)、list容器(双向链表)

1)、list容器的特性

list容器在物理上非连续,非顺序存储,在逻辑上是连续的,属于线性存储结构。

list含有迭代器,使用双向迭代器。没有容器的概念没有容量的概念

list 构造函数
list<T> lstT;//list 采用采用模板类实现,对象的默认构造形式:
list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);//构造函数将 n 个 elem 拷贝给本身。
list(const list &lst);//拷贝构造函数。
 list 数据元素插入和删除操作
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在 pos 位置插 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据千锋教育——用良心做教育 http://www.mobiletrain.org/
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与 elem 值匹配的元素。
list 大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(num);//重新指定容器的长度为 num,
//若容器变长,则以默认值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
resize(num, elem);//重新指定容器的长度为 num,
//若容器变长,则以 elem 值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
list 赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
list& operator=(const list &lst);//重载等号操作符
swap(lst);//将 lst 与本身的元素互换。
list 数据的存取
front();//返回第一个元素。
back();//返回最后一个元素。
3.6.4.6 list 反转排序
reverse();//反转链表,比如 lst 包含 1,3,5 元素,运行此方法后, lst 就包含 5,3,1
元素。
sort(); //list 排序

案例:

#include <iostream>
#include<list>


using namespace std;
void printListInt(list<int> &l)
{
    list<int>::iterator it = l.begin();
    for(;it != l.end(); it++)
        cout << *it << " ";
    cout << endl;
}
void test01()
{
    list<int> l1;
    l1.push_back(10);
    l1.push_back(20);
    l1.push_back(30);
    l1.push_front(40);
    l1.push_front(50);
    l1.push_front(60);

    cout << "大小为 : " << l1.size() << endl;
    printListInt(l1);

    list<int>::iterator it = l1.begin();
    //list容器不支持+/-运算
    it++;
    l1.insert(it, 3, 100);
    printListInt(l1);

    l1.remove(100);
    printListInt(l1);

    l1.reverse();
    printListInt(l1);
    //STL提供的sort只支持随机访问迭代器,不支持双向迭代器
    //sort(l1.begin(), l1.end());
    l1.sort();
    printListInt(l1);

}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

(8)、set和multiset容器

1)、set容器的特性

1.会根据元素的键值自动排序(从小到大),插入数据时会根据键值自动排号顺序,底层用树实现。

2.set的键值和实值是一个值,不允许两个元素有相同的键值,不允许任意修改set元素的值。

迭代器类型为const_iterator

set容器的基本遍历:

#include <iostream>
#include<set>
#include<algorithm>
using namespace std;
void myprintf(set<int>&s)
{   //set容器存放后自动排序并且不能改变里面的元素,否则破坏顺序
   set<int>::const_iterator it =s.begin();
   for(;it != s.end();it++)
   {
       cout<<*it<<" ";
   }
   cout<<endl;
}

void test01()
{   //set容器里面的值不能重复,multiset容器值可以重复
    //俩个容器只有键值没有实值
    set<int>s;
    s.insert(50);
    s.insert(30);
    s.insert(20);
    s.insert(10);
    s.insert(400);

    myprintf(s);
}


int main(int argc, char *argv[])
{
    test01();
    return 0;
}

set容器默认从小到大排序,我们修改他的排序顺序(从大到小):

set容器没有reverse也没有reverse iterator所以用仿函数实现逆向排序的函数功能

#include <iostream>
#include<set>
#include<algorithm>
using namespace std;

class Mgreater
{

public:
    //重载匿名对象仿函数,按照从大到小排序
    bool operator()(int a,int b)
    {
        return a>b;
    }
};
void myprintf(set<int,Mgreater>&s)
{   //set容器存放后自动排序并且不能改变里面的元素,否则破坏顺序
   set<int,Mgreater>::const_iterator it =s.begin();
   for(;it != s.end();it++)
   {
       cout<<*it<<" ";
   }
   cout<<endl;
}
void test01()
{   //set容器里面的值不能重复,multiset容器值可以重复
    //俩个容器只有键值没有实值

    set<int,Mgreater>s;
    //这里的Mgreater类会创建匿名对象Mygreater()()重载仿函数
    //重载之后的仿函数相当于函数,可以之间接收数据,并且比较大小
    s.insert(50);
    s.insert(30);
    s.insert(20);
    s.insert(10);
    s.insert(40);

    myprintf(s);
}


int main(int argc, char *argv[])
{
    test01();
    return 0;
}

 set容器存放自定义类必须使用仿函数来排序:

自定义数据类型无返自动比较大小。仿函数重载。

#include <iostream>
#include<set>
#include<algorithm>
using namespace std;
//set容器存放自定义数据类型,必须要重载仿函数,因为无法确认比较哪个参数

class mygreater;
//自定义数据类型
class person
{   friend void print(set<person,mygreater>&s);
    friend class mygreater;
private:
    int num;
    string name;
    float score;
public:
    person(){}
    person(int num,string name,float score):num(num),name(name),score(score){}

};
//重载仿函数(),传入类具体去比较大小
class mygreater
{
public:
    bool operator()(person ob1,person ob2)
    {
        return ob1.num>ob2.num;
    }
};
void print(set<person,mygreater>&s)
{
    set<person,mygreater>::const_iterator it=s.begin();
    //这里的*it代表的是person类而不是成员
    for(;it !=s.end();it++ )
    {
        cout<<(*it).num<<" ";
    }
    cout<<endl;
}
void test01()
{   //用mygreater去实现重载仿函数,达到比较大小的目的
    set<person,mygreater>s;
    s.insert(person(10,"hh",0.0f));
    s.insert(person(50,"ha",0.0f));
    s.insert(person(20,"hx",0.0f));
    s.insert(person(40,"hd",0.0f));
    s.insert(person(30,"hc",0.0f));

    print(s);

}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

2)、multiset容器的特性

multiset与set的特性与用法基本一致,mutilset允许键值重复。底层的实现也是利用红黑树。

setmultiset 是 C++ STL 中的关联容器,它们都基于红黑树实现,并提供了一些常用的操作,如插入、删除、查找等。

setmultiset 的不同之处在于元素的唯一性:

  1. setset 容器中的元素是唯一的,即不允许重复元素。当插入一个已存在的元素时,插入操作会被忽略。

  2. multisetmultiset 容器中的元素允许重复。可以插入多个相同的元素,并且在搜索时可以找到所有相同的元素。

这两个容器都支持以下操作:

  1. 插入元素:可以使用 insert() 函数将元素插入到容器中。时间复杂度为 O(log n)。

  2. 删除元素:可以使用 erase() 函数删除指定的元素。时间复杂度为 O(log n)。

  3. 查找元素:可以使用 find() 函数来查找指定的元素,如果找到则返回元素的迭代器,否则返回容器末尾的迭代器。时间复杂度为 O(log n)。

此外,setmultiset 还提供了其他一些常用操作,如大小判断、遍历等。

需要注意的是,由于 setmultiset 内部使用红黑树实现,其总体性能较好,但相对于向量容器(vector)等,它们可能会有更高的内存使用和插入/删除操作的开销。因此,在选择使用 setmultiset 时,需要根据具体需求权衡其优缺点和性能特点。

红黑树的具体实现:

3)、常用API

set 构造函数
set<T> st;//set 默认构造函数:
mulitset<T> mst; //multiset 默认构造函数:
set(const set &st);//拷贝构造函数
set 赋值操作
set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器
set 大小操作
size();//返回容器中元素的数目
empty();//判断容器是否为空
set 插入和删除操作
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);//删除容器中值为 elem 的元素。
set 查找操作
find(key);//查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回 set.end();
count(key);//查找键 key 的元素个数
lower_bound(keyElem);//返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器

例子:实现set的从大到小排序(只有利用红黑树的容器才可以)

#include <iostream>
#include<set>


using namespace std;
struct MyGreater
{
    bool operator()(int num1, int num2)
    {
        return num1 > num2;
    }
};

void printSetInt( set<int>& s)
{
    for (auto it = s.begin(); it != s.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
}
void printSetInt(set<int, MyGreater> &s)
{

    for(auto it = s.begin();it != s.end(); it++){
        cout <<"+ " << *it << "  ";
    }
    cout << endl;
}
void test01()
{
    set<int, MyGreater> s1;

    s1.insert(30);
    s1.insert(50);
    s1.insert(10);
    s1.insert(20);
    s1.insert(40);

    printSetInt(s1);
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

案例2:set容器存放自定义数据

class Person;


class LessPerson
{
public:
    bool operator()(Person ob1, Person ob2);
};
class Person
{   friend void printSetPerson(set<Person, LessPerson> &s);
    friend class LessPerson;
private:
    int num;
    string name;
public:
    Person() {}
    Person(int num, string name)
    {
        this->num = num;
        this->name = name;
    }
  /*  bool operator<(Person &ob)
    {
        return this->num < ob.num;
    }*/
};


void printSetPerson(set<Person, LessPerson> &s)
{
    set<Person>::const_iterator it = s.begin();
    for(; it != s.end(); it ++)
    {
        //*it  --->Person
        cout <<(*it).num << "  " << (*it).name << endl;
    }
}
void test01()
{
    set<Person, LessPerson> s;
    s.insert(Person(105, "lucy"));
    s.insert(Person(102, "bob"));
    s.insert(Person(103, "white"));
    s.insert(Person(104, "eric"));
    s.insert(Person(101, "frike"));


    printSetPerson(s);
}
int main(int argc, char *argv[])
{
    test01();
    return 0;
}

bool LessPerson::operator()(Person ob1, Person ob2)
{
    return ob1.num < ob2.num;
}

案例3:find、count、lower_bound、upper_bound、equal_range应用

count(计数):

void test05()
{
    set<int>s;
    s.insert(10);
    s.insert(20);
    s.insert(30);
    s.insert(40);
    s.insert(50);
    //cout计数在set中只有0和1,因为set中重复元素会被覆盖
    int ret=s.count(10);
    cout<<ret<<endl;
}

find(查找元素的位置返回迭代器) 

void test02()
{
    set<int>s;
    s.insert(10);
    s.insert(20);
    s.insert(30);
    s.insert(40);
    s.insert(50);

    //find寻找某个值的位置,返回的是迭代器
    set<int>::const_iterator ret;
    ret = s.find(50);
    if(ret != s.end())
    {
        cout<<*ret<<endl;
    }
}

lower_bound(下限),upper_bound(上限)返回值也是迭代器

void test03()
{
    set<int>s;
    s.insert(10);
    s.insert(20);
    s.insert(30);
    s.insert(40);
    s.insert(50);

    set<int>::iterator ret;
    ret = s.lower_bound(40);
    if(ret != s.end())
    {
        cout<<"下限为"<<*ret<<endl;
    }
    ret = s.upper_bound(40);
    if(ret != s.end())
    {
        cout<<"上限为"<<*ret<<endl;
    }
}

equal_range(上下限)由于返回值是俩个所以用对组存放

//以对组的方式存储上下限
void test04()
{
    set<int>s;
    s.insert(10);
    s.insert(20);
    s.insert(30);
    s.insert(40);
    s.insert(50);
    //由于C++返回值只有一个,这个返回值是一个下限一个上限,用pair来接收。
    pair<set<int>::iterator,set<int>::iterator> pa;
    //pa里面第一个存放的是下限,第二个是上线
    pa =s.equal_range(40);
    if(pa.first != s.end())
    {
        cout<<"下限是"<<*(pa.first)<<endl;
    }if(pa.second != s.end())
    {
        cout<<"下限是"<<*(pa.second)<<endl;
    }
}

案例4:multiset使用

void test03()
{
    multiset<int> s;
    s.insert(10);
    s.insert(10);
    s.insert(10);
    s.insert(10);
    s.insert(10);


    cout << s.count(10) << endl;


    multiset<int>::const_iterator it = s.begin();
    for(; it != s.end(); it++)
        cout << *it << "  ";
    cout << endl;
}

(9)、对组

1)、对组的特性

对组(pair)将一对值组合成一个值,这一对值可以有不同的数据类型,俩个值可以分别用pair的俩个公有属性first和second访问。

类模板: template struct pair.

//对组,是一个类模板,存放俩种不同的数据类型
void test06()
{
    pair<int,string>p1(10,"bob");
    cout<<p1.first<<" "<<p1.second<<endl;

    pair<int,string>p2=make_pair(10,"bob");
    cout<<p1.first<<" "<<p1.second<<endl;
}

(10)、map/multimap容器

map 的特性是,所有元素都会根据元素的键值自动排序。 map 所有的元素都是pair,同时拥有实值和键值, pair 的第一元素被视为键值,第二元素被视为实值,map 不允许两个元素有相同的键值,键值不能修改。multimap允许键值重复。

map和multimap容器的迭代器是const_iterator(只读迭代器)

1)、常用API

map 构造函数
map<T1, T2> mapTT;//map 默认构造函数:
map(const map &mp);//拷贝构造函数
map 赋值操作
map& operator=(const map &mp);//重载等号操作符
swap(mp);//交换两个集合容器
map 大小操作
size();//返回容器中元素的数目
empty();//判断容器是否为空
插入数据元素操作map.
insert(...); //往容器插入元素,返回 pair<iterator,bool>

案例1:map容器插入与遍历

void test01()
{
    map<int, string> m;
    //方式1:
    m.insert(pair<int,string>(10086, "移动"));
    //方式2:
    m.insert(make_pair(10010, "联通")); ///< 建议使用
    //方式3:
    m.insert(map<int, string>::value_type(10000, "电信"));
    //方式4:
    m[9527] = "华安";

    map<int, string>::const_iterator it = m.begin();
    for(;it != m.end(); it++){
        cout << "键值: " << (*it).first << " 实值" << (*it).second << endl;
    }
}

案例2:map存储私有数据

class Person
{   friend void printMapPerson(map<int, Person> &m);
private:
    int num;
    string name;
public:
    Person() {}
    Person(int num, string name)
    {
        this->num = num;
        this->name = name;
    }
};
void printMapPerson(map<int, Person> &m)
{
    map<int,Person>::const_iterator it = m.begin();
    for(;it != m.end(); it++){
        //*it <int, string>
        cout <<"学号为:" << (*it).first << " 姓名" << (*it).second.name << endl;
    }
}
void test02()
{
    map<int, Person> m;
    m.insert(make_pair(101, Person(101, "lucy")));
    m.insert(make_pair(103, Person(103, "bob")));
    m.insert(make_pair(102, Person(102, "white")));


    printMapPerson(m);
}

案例:公司今天招聘了 5 个员工, 5 名员工进入公司之后,需要指派员工在那个部门工作人员信息有: 姓名 年龄 电话 工资等组成

通过 Multimap 进行信息的插入 保存 显示分部门显示员工信息 显示全部员工信息

#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <ctime>


using namespace std;
class Person
{
    friend void createPerson(vector<Person> &v);
    friend void personJoinDepartment(vector<Person> &v, multimap<int, Person> &m);
    friend void showPersonDepartment(multimap<int, Person> m, int op);
private:
    string name;
    int age;
    string tel;
    int money;
public:
    Person() {}
    Person(string name, int age, string tel, int money)
    {
        this->name = name;
        this->age = age;
        this->tel = tel;
        this->money = money;
    }
};
void createPerson(vector<Person> &v)
{
    srand(time(NULL));
    string tmpName = "ABCDE";
    for(int i = 0; i < 5; i++)
    {
        string name = "员工";
        name += tmpName[i];
        int age = rand()%5 + 20;
        int money = rand()%5000 + 10000;
        string tel = to_string(rand());

        v.push_back(Person(name, age, tel, money));
    }
}
void personJoinDepartment(vector<Person> &v, multimap<int, Person> &m)
{
    vector<Person>::iterator it = v.begin();
    for(;it != v.end(); it++){
        //*it == Person
        cout << "请输入" << (*it).name <<"想要加入的部门:1(销售)、2(研发)、3(财务):";
        int op = 0;
        cin >> op;
        m.insert(make_pair(op, *it));
    }
}
void showPersonDepartment(multimap<int, Person> m, int op)
{
    //显示哪个部门
    multimap<int, Person>::const_iterator ret;
    ret = m.find(op);
    if(ret == m.end()){
        cout<< "未找到该部门的员工信息" << endl;
        return;
    }
    int count = m.count(op);
    switch (op) {
    case 1:
        cout << "销售部:" << endl;
        break;
    case 2:
        cout << "研发部:" << endl;
        break;
    case 3:
        cout << "财务部:" << endl;
        break;
    default:
        break;
    }
    for(int j = 0; j < count; j++, ret++)
    {
        cout << (*ret).second.name << "  " << (*ret).second.age << "  " << \
                (*ret).second.money << "  " << (*ret).second.tel << endl;
    }


}
int main(int argc, char *argv[])
{
    multimap<int, Person> m;

    //创建存放员工的容器(vector)
    vector<Person> v;
    createPerson(v);

    //将员工加入部门
    personJoinDepartment(v, m);

    //显示部门的员工
    while(1){
        cout << "请输入要显示的部门:1(销售)、2(研发)、3(财务):";
        int op = 0;
        cin >> op;
        showPersonDepartment(m, op);
    }
    return 0;
}

(11)、STL容器的总结:

vector容器:单端动态数组 随机访问迭代器 经常用于数据的临时存储。

deque容器:双端动态数组 随机访问迭代器

stack容器: 没有迭代器 先进后出

queue容器: 没有迭代器 先进先出

list容器:双向链表 双向迭代器

set/multiset容器:只有键值 set键值不能重复 自动排序 不能修改内部元素的值 只读迭代器

map/multimap容器:键值--实值 map键值不能重复 成对出现(键值与实值)自动排序 只读迭代器

3、算法:

(1)、仿函数(函数对象)

仿函数就是利用运算符重载(),把实例化的对象作为函数来使用。

class MyPrint
{
public:
    void operator()(string str)
    {
        cout << str << endl;
    }
};
void test01()
{
    MyPrint ob;
    ob("hello world");

    //创建匿名对象
    MyPrint()("hello world");
}

(2)、谓词

返回值为bool类型的普通函数或者仿函数(为函数内部提供条件判断)

有一个参数叫一元谓词

有两个参数叫二元谓词

案例1:一元谓词使用

class Greater
{
public:
    bool operator()(int val)
    {
        return val > 20;
    }
};
bool my_greater(int val)
{
    return val > 30;
}
void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);

    vector<int>::iterator ret;
  //  ret = find_if(v.begin(), v.end(), Greater());
    ret = find_if(v.begin(), v.end(), my_greater);
    if(ret != v.end()){
        cout << *ret << endl;
    }
}
案例2:二元谓词使用
class MyGreater
{
public:
    bool operator()(int v1, int v2)
    {
        return v1 > v2;
    }

案例2:二元谓词使用

class MyGreater
{
public:
    bool operator()(int v1, int v2)
    {
        return v1 > v2;
    }
};
bool myGreater(int v1, int v2)
{
    return v1 > v2;
}
void test02()
{
    vector<int> v;
    v.push_back(20);
    v.push_back(40);
    v.push_back(10);
    v.push_back(50);
    v.push_back(30);


    for_each(v.begin(), v.end(), my_print);
    cout << endl;
    //排序的默认顺序:小 --- 大
    sort(v.begin(), v.end());


    for_each(v.begin(), v.end(), my_print);
    cout << endl;


   // sort(v.begin(), v.end(), MyGreater());
    sort(v.begin(), v.end(), myGreater);
    for_each(v.begin(), v.end(), my_print);
    cout << endl;
}

(3)、内建函数对象(由STL提供的函数对象)

6 个算数类函数对象,除了 negate 是一元运算,其他都是二元运算

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 modulus<T>//取模仿函数
template<class T> T negate<T>//取反仿函数

6 个关系运算类函数对象,每一种都是二元运算

template<class T> bool equal_to<T>//等于
template<class T> bool not_equal_to<T>//不等于
template<class T> bool greater<T>//大于
template<class T> bool greater_equal<T>//大于等于
template<class T> bool less<T>//小于
template<class T> bool less_equal<T>//小于等于

逻辑运算类运算函数,not 为一元运算,其余为二元运算

template<class T> bool logical_and<T>//逻辑与
template<class T> bool logical_or<T>//逻辑或
template<class T> bool logical_not<T>//逻辑非

案例1:利用内建函数对象实现从大到小排序

sort(v.begin(), v.end(), greater<int>());

下面是简单的greater<int>原型,也可以是某个类

template <typename T>
struct greater {
    bool operator()(const T& a, const T& b) const {
        return a > b;
    }
};

4、适配器:

适配器可以将类适配到另一个不兼容的接口

(1)、函数对象作为适配器

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


using namespace std;
//1.公共继承binary_function<参数列表(类型,顺序), 返回值类型>
class MyPrint:public binary_function<int, int, void>
{
public:   //2.用const修饰函数调用运算重载
    void operator()(int val, int tmp) const
    {
        cout << val << "  " << tmp << endl;
        cout << val + tmp << endl;
    }
};
void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
    //bin1st与bind2nd进行参数绑定,将参数绑定到函数对象第几个形参上
    for_each(v.begin(), v.end(), bind1st(MyPrint(), 100));
}
int main(int argc, char *argv[])
{
    test01();
    return 0;
}

bind1st : 将参数绑定为函数对象的第一个参数

bind2nd : 将参数绑定为函数对象的第二个参数

(2)、函数指针作为适配器

for_each(v.begin(), v.end(), bind1st(ptr_fun(myPrint)

void myPrint(int val, int tmp)
{
    cout << val << "  " << tmp << endl;
    cout << val + tmp << endl;
}

//函数指针做适配器,要在函数名前加上ptr_fun
 for_each(v.begin(), v.end(), bind1st(ptr_fun(myPrint), 100));

(3)、成员函数做适配器

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


using namespace std;
//1.公共继承binary_function<参数列表(类型,顺序), 返回值类型>
class Data
{
private:
    int a;
public:
    Data() {}
    Data(int a):a(a){}
    void showData()
    {
        cout << a << endl;
    }
};
void test02()
{
    vector<Data> v;
    v.push_back(Data(10));
    v.push_back(Data(20));
    v.push_back(Data(30));
    v.push_back(Data(40));
    v.push_back(Data(50));

    for_each(v.begin(), v.end(), mem_fun_ref(&Data::showData));
}




int main(int argc, char *argv[])
{
    test02();
    return 0;
}

(4)、取反适配器、

not1 一元取反

not2 二元取反

用法:not1(表达式),但是一元取反与二元取反的选择需要考虑(表达式的参数)

案例:一元取反与二元取反

void test03()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);


    vector<int>::iterator ret;
    ret = find_if(v.begin(), v.end(), not1(bind2nd(greater<int>(), 30)));
    if(ret != v.end()){
        cout << "找到结果:" << *ret << endl;
    }


    //lambda表达式
    for_each(v.begin(), v.end(), [](int val){
        cout << val << " ";
    });
    cout << endl;

    sort(v.begin(), v.end(), greater<int>());
    for_each(v.begin(), v.end(), [](int val){
        cout << val << " ";
    });
    cout << endl;
    sort(v.begin(), v.end(), not2(greater<int>()));

    for_each(v.begin(), v.end(), [](int val){
        cout << val << " ";
    });
    cout << endl;
}

5、常用算法:

(1)、遍历算法

for_each遍历算法 遍历容器元素

/*
@param beg 开始迭代器
@param end 结束迭代器
@param _callback 函数回调或者函数对象
@return 函数对象
*/
for_each(iterator beg, iterator end, _callback);

(2)、transform算法

int func01(int val)
{
    return (val + 100);
}
/*
transform 算法 将指定容器区间元素搬运到另一容器中
注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
@param beg1 源容器开始迭代器
@param end1 源容器结束迭代器
@param beg2 目标容器开始迭代器
@param _cakkback 回调函数或者函数对象
@return 返回目标容器迭代器
transform(iterator beg1, iterator end1, iterator beg2, _callbakc);
*/
void test01()
{
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);


    vector<int> v2;
    v2.resize(v1.size());


    transform(v1.begin(), v1.end(), v2.begin(), func01);


    for_each(v2.begin(), v2.end(), [](int val){
       cout << val << "  " ;
    });
    cout << endl;
}

(3)、find 算法 查找元素

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return 返回查找元素的位置
*/
find(iterator beg, iterator end, value)
/*

(4)、find_if 算法 条件查找

@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 回调函数或者谓词(返回 bool 类型的函数对象)
@return bool 查找返回 true 否则 false
*/
find_if(iterator beg, iterator end, _callback);

(5)、adjacent_find 算法

/*
adjacent_find 算法 查找相邻重复元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param _callback 回调函数或者谓词(返回 bool 类型的函数对象)
@return 返回相邻元素的第一个位置的迭代器
adjacent_find(iterator beg, iterator end, _callback);
*/
void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(20);
    v.push_back(30);
    v.push_back(30);


    vector<int>::iterator ret;
    ret = adjacent_find(v.begin(), v.end());
    if(ret != v.end())
        cout << *ret << endl;
}

(6)、binary_search 算法 二分查找法

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

/*
adjacent_find 算法 查找相邻重复元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param _callback 回调函数或者谓词(返回 bool 类型的函数对象)
@return 返回相邻元素的第一个位置的迭代器
*/
adjacent_find(iterator beg, iterator end, _callback);

(7)、binary_search二分法查找算法

/*
binary_search 算法 二分查找法
注意: 在无序序列中不可用
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return bool 查找返回 true 否则 false
*/
void test02()
{
   vector<int> v;
   v.push_back(10);
   v.push_back(20);
   v.push_back(30);
   v.push_back(40);

   bool ret = binary_search(v.begin(), v.end(), 20);
   if(ret)
       cout << "有" << endl;
   else
       cout << "没有" << endl;
}

(8)、count 算法 统计元素出现次数

/*
count 算法 统计元素出现次数
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 回调函数或者谓词(返回 bool 类型的函数对象)
@return int 返回元素个数
*/
count(iterator beg, iterator end, value);

(9)、count_if算法统计元素出现次数

/*
count_if 算法 统计元素出现次数
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 回调函数或者谓词(返回 bool 类型的函数对象)
@return int 返回元素个数
count_if(iterator beg, iterator end, _callback);
*/
void test03()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);


    cout << count_if(v.begin(), v.end(), bind2nd(greater<int>(), 20)) << endl;
}

(10)、排序算法 merge 合并

merge 算法 容器元素合并,并存储到另一容器中

注意:两个容器必须是有序的

/*
merge 算法 容器元素合并,并存储到另一容器中
注意:两个容器必须是有序的
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, itera
tor dest)*/
void test04()
{
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(40);


    vector<int> v2;
    v2.push_back(20);
    v2.push_back(30);
    v2.push_back(60);


    vector<int> v3;
    v3.resize(v1.size() + v2.size());


    merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin());
    for_each(v3.begin(), v3.end(), [](int val){
        cout << val << "  ";
    });
    cout << endl;
}

(11)、sort排序算法

/*
sort 算法 容器元素排序
@param beg 容器 1 开始迭代器
@param end 容器 1 结束迭代器
@param _callback 回调函数或者谓词(返回 bool 类型的函数对象)
*/
sort(iterator beg, iterator end, _callback)

(12)、random_shuffle 洗牌算法

打乱容器内元素的顺序

/*
random_shuffle 算法 对指定范围内的元素随机调整次序
@param beg 容器开始迭代器
@param end 容器结束迭代器
random_shuffle(iterator beg, iterator end)
*/
#include <ctime>
void test05()
{
    srand(time(NULL));
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);


    random_shuffle(v.begin(), v.end());


    for_each(v.begin(), v.end(), [](int val){
        cout << val << "  ";
    });
    cout << endl;
}

(13)、reverse 算法 反转指定范围的元素

/*
reverse 算法 反转指定范围的元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
*/
reverse(iterator beg, iterator end)

(14)、copy 算法 将容器内指定范围的元素拷贝到另一容器中

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param dest 目标起始迭代器
*/
copy(iterator beg, iterator end, iterator dest)
void test06()
{
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);


    vector<int> v2;
    v2.resize(v1.size());


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


    for_each(v2.begin(), v2.end(), [](int val){
        cout << val << "  ";
    });
    cout << endl;


    copy(v2.begin(), v2.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
}

(15)、replace 算法 将容器内指定范围的旧元素修改为新元素

/*
replace 算法 将容器内指定范围的旧元素修改为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param oldvalue 旧元素
@param oldvalue 新元素
*/

replace(iterator beg, iterator end, oldvalue, newvalue);

/*
replace_if 算法 将容器内指定范围满足条件的元素替换为新元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param callback 函数回调或者谓词(返回 Bool 类型的函数对象)
@param oldvalue 新元素
*/
replace_if(iterator beg, iterator end, _callback, newvalue)
void test07()
{
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    v1.push_back(50);


    replace_if(v1.begin(), v1.end(), bind2nd(greater<int>(), 30), 60);


    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
}

(16)、accmulate 算法 计算容器元素累计总和

/*
accumulate 算法 计算容器元素累计总和
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 累加值
*/
accumulate(iterator beg, iterator end, value)

(17)、fill 算法 向容器中添加元素

初始化容器时以value填充容器元素值

/*
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value t 填充元素
*/
fill(iterator beg, iterator end, value)

(18)、常用集合算法

/*
set_intersection 算法 求两个 set 集合的交集
注意:两个集合必须是有序序列
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator 
end2, iterator dest)
/*
set_union 算法 求两个 set 集合的并集
注意:两个集合必须是有序序列
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, i
terator dest)
/*
set_difference 算法 求两个 set 集合的差集
注意:两个集合必须是有序序列
@param beg1 容器 1 开始迭代器
@param end1 容器 1 结束迭代器
@param beg2 容器 2 开始迭代器
@param end2 容器 2 结束迭代器
@param dest 目标容器开始迭代器
@return 目标容器的最后一个元素的迭代器地址
*/
set_difference(iterator beg1, iterator end1, iterator beg2, iterator en
d2, iterator dest)

注意:操作后的结果也是放到容器中,此时我们需要考虑目标容器的大小。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值