【C++】算法STL库

26 算法STL库

26.1 算法特点

使用迭代器指定范围,使用函数作为参数处理数据。

26.2 算法的两个主要泛型元素

1.模板提供泛型类型 ​ 2.迭代器提供数据的通用访问表示

26.3 算法分组

前三组定义在algorithm头文件中,最后一组定义在numeric头文件中 ​ 1.非修改序列操作组:对范围内的每个元素进行操作。这些操作保持容器不变;find(),for_each() ​ 2.突变序列操作组:也可以对范围内的每个元素进行操作。可以改变或改变容器的内容(更改值或更改顺序);transform(),random_shuffle(),copy() ​ 3.排序和相关操作组:包括几个排序函数(包括sort())和各种其他函数,包括集合操作。 ​ 4.数据操作组:包括对范围内的数据求和、计算两个容器的内积、计算部分和、计算相邻差等等;它的操作主要是针对数组,因此vector是其主要操作容器

26.4 算法的一般性质

这个声明告诉你range形参必须是输入迭代器或更好的,指示结果位置的迭代器必须是输出形参或更好的:

template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);

根据处理后的元素被放在哪里对算法进行分类: ​ 1.in-place algorithm:处理后的元素覆盖原始容器 ​ 2.copying algorithm:处理后的元素复制给别的容器 ​ 3.一些算法有两种版本:一个in-place algorithm版本,一个copying algorithm版本,比如transform()可以输出到别的容器,也允许输出给输入的容器。 ​ STL约定给函数名添加 _ copy 后缀指定复制版本,复制版本将接收一个额外的输出迭代器参数,该参数指定结果的放置位置。

//一般版本
template<class ForwardIterator, class T>
void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value);
//复制版本---返回的迭代器指向复制的最后一个值后面的一个位置。
template<class InputIterator, class OutputIterator, class T>
OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value);

4.还有一种变体,根据 对容器元素执行操作 的返回条件(当返回true时执行)决定是否对该元素执行操作。 ​ STL规定给函数名添加if后缀指定条件版本

template<class ForwardIterator, class Predicate class T>
void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value);//Predicate为返回一个bool值的仿函数

5.既是复制版本也是if版本,给函数名添加_copy_if后缀指定

26.5 注意事项

前面的ForwardIterator、InputIterator、Predicate等等都是STL给程序员的提示,但是编译器无法检查这些名称(C++没有真的实现这种类,只是一种理论) 如果使用了错误类型的迭代器,在编译器试图实例化模板时,您可能会看到一长串错误消息。

26.6 STL和string类

此处就是讲了对string字符串的排列 ​ next_permutation(letters.begin(), letters.end())---就是对letters(string类)进行一个排列,不断获取排列(成功返回true)直到所有排列获取完成,函数返回false,只提供不重复的排列

26.7 函数 VS 容器方法

有些时候既可以使用函数也可以使用容器方法,但是建议使用容器方法,原因如下: 1.针对特定的容器,容器方法的实现更贴合 2.作为成员函数,可以使用模板类存储管理机制,可以根据需要调整容器的大小,虽然容器方法更合适,但是函数更泛化。

26.8 使用STL

STL是一个库,它的各个部分被设计成协同工作。STL组件是工具,但它们也是创建其他工具的构建块。 使用STL的原则时尽量少自己敲代码。 举例为:首先输入n个单词,然后将其存储及显示;不区分大小写地记录不重复的单词并存储显示,计算每个单词出现的次数并存储显示

26.9 举例

代码

/*
Project name :          _29Algorithms
Last modified Date:     2022年4月19日11点09分
Last Version:           V1.0
Descriptions:           算法
*/
/*
算法特点:使用迭代器指定范围,使用函数作为参数处理数据。
算法的两个主要泛型元素:
    1.模板提供泛型类型
    2.迭代器提供数据的通用访问表示
算法分组:
    前三组定义在algorithm头文件中,最后一组定义在numeric头文件中
    1.非修改序列操作组:对范围内的每个元素进行操作。这些操作保持容器不变;find(),for_each()
    2.突变序列操作组:也可以对范围内的每个元素进行操作。可以改变或改变容器的内容(更改值或更改顺序);transform(),random_shuffle(),copy()
    3.排序和相关操作组:包括几个排序函数(包括sort())和各种其他函数,包括集合操作。
    4.数据操作组:包括对范围内的数据求和、计算两个容器的内积、计算部分和、计算相邻差等等;它的操作主要是针对数组,因此vector是其主要操作容器
算法的一般性质:
    使用InputIterator和OutputIterator说明需要使用的是输入迭代器
    template<class InputIterator, class OutputIterator>
    OutputIterator copy(InputIterator first, InputIterator last,
        OutputIterator result);
    根据处理后的元素被放在哪里对算法进行分类:
        1.in-place algorithm:处理后的元素覆盖原始容器
        2.copying algorithm:处理后的元素复制给别的容器
        3.一些算法有两种版本:一个in-place algorithm版本,一个copying algorithm版本,比如transform()可以输出到别的容器,也允许输出给输入的容器。
            STL约定给函数名添加_copy后缀指定复制版本,复制版本将接收一个额外的输出迭代器参数,该参数指定结果的放置位置。
            //一般版本
            template<class ForwardIterator, class T>
            void replace(ForwardIterator first, ForwardIterator last,
                const T& old_value, const T& new_value);
            //复制版本---返回的迭代器指向复制的最后一个值后面的一个位置。
            template<class InputIterator, class OutputIterator, class T>
            OutputIterator replace_copy(InputIterator first, InputIterator last,
                OutputIterator result,
                const T& old_value, const T& new_value);
        4.还有一种变体,根据 对容器元素执行操作 的返回条件(当返回true时执行)决定是否对该元素执行操作。
            STL规定给函数名添加_if后缀指定条件版本
            template<class ForwardIterator, class Predicate class T>
            void replace_if(ForwardIterator first, ForwardIterator last,
                Predicate pred, const T& new_value);//Predicate为返回一个bool值的伪函数
        5.既是复制版本也是if版本,给函数名添加_copy_if后缀指定
注意事项:前面的ForwardIterator、InputIterator、Predicate等等都是STL给程序员的提示,但是编译器无法检查这些名称(C++没有真的实现这种类,只是一种理论)
    如果使用了错误类型的迭代器,在编译器试图实例化模板时,您可能会看到一长串错误消息。
STL和string类
    此处就是讲了对string字符串的排列
    next_permutation(letters.begin(), letters.end())---就是对letters(string类)进行一个排列,不断获取排列(成功返回true)直到所有排列获取完成,函数返回false
        只提供不重复的排列
函数 VS 容器方法:有些时候既可以使用函数也可以使用容器方法,但是建议使用容器方法,原因如下:
    1.针对特定的容器,容器方法的实现更贴合
    2.作为成员函数,可以使用模板类存储管理机制,可以根据需要调整容器的大小
    虽然容器方法更合适,但是函数更泛化。
使用STL:STL是一个库,它的各个部分被设计成协同工作。STL组件是工具,但它们也是创建其他工具的构建块。
    使用STL的原则时尽量少自己敲代码。
    举例为:首先输入n个单词,然后将其存储及显示;不区分大小写地记录不重复的单词并存储显示,计算每个单词出现的次数并存储显示
*/
​
​
// strgstl.cpp -- applying the STL to a string
#include <iostream>
#include <string>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iterator>
#include <cctype>
using namespace std;
void Show(int);
const int LIM = 10;
​
char toLower(char ch) { return tolower(ch); }//int tolower(int)---toLower()这个函数是为了兼容本举例要求而写
string& ToLower(string& st);
void display(const string& s);
int main()
{
    string letters;
    cout << "string class and STL**************************************************************" << endl;
    cout << "Enter the letter grouping (quit to quit): ";
    while (cin >> letters && letters != "quit")
    {
        cout << "Permutations of " << letters << endl;
        sort(letters.begin(), letters.end());
        cout << letters << endl;
        while (next_permutation(letters.begin(), letters.end()))
            cout << letters << endl;
        cout << "Enter next sequence (quit to quit): ";
    }
    cout << "Functions Versus Container Methods***********************************************" << endl;
    int ar[LIM] = { 4, 5, 4, 2, 2, 3, 4, 8, 1, 4 };
    list<int> la(ar, ar + LIM);
    list<int> lb(la);
    cout << "Original list contents:\n\t";
    for_each(la.begin(), la.end(), Show);
    cout << endl;
    la.remove(4);//此处自动调整大小
    cout << "After using the remove() method:\n";
    cout << "la:\t";
    for_each(la.begin(), la.end(), Show);
    cout << endl;
    list<int>::iterator last;
    last = remove(lb.begin(), lb.end(), 4);//此处没有自动调整大小,而只是返回了移除元素后列表的end
    cout << "After using the remove() function:\n";
    cout << "lb:\t";
    for_each(lb.begin(), lb.end(), Show);
    cout << endl;
    lb.erase(last, lb.end());//需要手动使用成员函数list.erase()调整大小
    cout << "After using the erase() method:\n";
    cout << "lb:\t";
    for_each(lb.begin(), lb.end(), Show);
    cout << endl;
    cout << "Using the STL******************************************************************" << endl;
    vector<string> words;
    cout << "Enter words (enter quit to quit):\n";
    string input;
    while (cin >> input && input != "quit")  //输入字符串
        words.push_back(input);
    cout << "You entered the following words:\n";
    for_each(words.begin(), words.end(), display);  //显式初始字符串
    cout << endl;
    // place words in set, converting to lowercase
    set<string> wordset;
    transform(words.begin(), words.end(),
        insert_iterator<set<string> >(wordset, wordset.begin()),
        ToLower);//将字符串转换为小写后将其复制到set中,set中不允许重复元素,且根据字符自动排序
    cout << "\nAlphabetic list of words:\n";
    for_each(wordset.begin(), wordset.end(), display);//显示set
    cout << endl;
    // place word and frequency in map
    map<string, int> wordmap;
    set<string>::iterator si;
    for (si = wordset.begin(); si != wordset.end(); si++)
        wordmap[*si] = count(words.begin(), words.end(), *si);//计算各个单词出现的次数,并将其按键值和值存储到map中
    // display map contents
    cout << "\nWord frequency:\n";
    for (si = wordset.begin(); si != wordset.end(); si++)
        cout << *si << ": " << wordmap[*si] << endl;//显示键值和值
​
    return 0;
}
​
void Show(int v)
{
    std::cout << v << ' ';
}
​
//这个函数将字符串所有字符转换为小写
string& ToLower(string& st)
{
    transform(st.begin(), st.end(), st.begin(), toLower);
    return st;
}
void display(const string& s)
{
    cout << s << " ";
}

运行结果

string class and STL**************************************************************
Enter the letter grouping (quit to quit): liy
Permutations of liy
ily
iyl
liy
lyi
yil
yli
Enter next sequence (quit to quit): quit
Functions Versus Container Methods***********************************************
Original list contents:
        4 5 4 2 2 3 4 8 1 4
After using the remove() method:
la:     5 2 2 3 8 1
After using the remove() function:
lb:     5 2 2 3 8 1 4 8 1 4
After using the erase() method:
lb:     5 2 2 3 8 1
Using the STL******************************************************************
Enter words (enter quit to quit):
lit quit
You entered the following words:
lit
​
Alphabetic list of words:
lit
​
Word frequency:
lit: 1
​
D:\Prj\_C++Self\_29Algorithms\x64\Debug\_29Algorithms.exe (进程 2996)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenSAL1.1 包含了算法导论中所有数据结构算法以及其他内容,本资源为该算法的静态链接 内容如下(*号表示1.1版本新增内容): 数据结构:一般堆、二项堆、斐波那契堆、红黑树、通用散列(采用全域散列和完全散列技术)、不相交集合、任意维数组、高维对称数组。 图论算法(兼容有向图,无向图):广度和深度优先遍历、确定图是否存在回路、拓扑排序、强连通分支、欧拉环(欧拉路径)、最小生成树(Kruskal、Prim)、单源最短路径(3种)、每对顶点间最短路径(2种)、最大流(2种)等等。 代数算法:霍纳法则计算多项式和、矩阵乘法(2种)、方阵的LUP分解、解线性方程组(2种)、矩阵求逆(2种)、求伪逆矩阵(2种)、解正态方程组(2种)、最小二乘估计(2种)、多元最小二乘估计*、快速傅里叶变换、快速傅里叶逆变换、多维快速傅里叶变换、多维快速傅里叶逆变换、快速向量求卷积(单变量多项式乘积)、快速张量求卷积(多变量多项式乘积)、多项式除法*、快速方幂和算法。 序列算法:最长公共子序列、KMP序列匹配*、键值分离排序。 数论算法:大数类(兼容浮点数、整数、与内置类型兼容运算)*、RSA加解密系统*、解同余方程*、孙子定理解同余方程组*、Miller_Rabin素数测试(产生大质数)*、随机数(实数、大数)*、欧几里得算法*。 计算几何算法:确定任意一对线段是否相交*、凸包*、最近点对*。 运筹学:线性规划(单纯形法)*、分配问题*、最优二度子图*、多01背包问题*
OpenSAL1.1 包含了算法导论中所有数据结构算法以及其他内容,本资源为该算法的动态链接 内容如下(*号表示1.1版本新增内容): 数据结构:一般堆、二项堆、斐波那契堆、红黑树、通用散列(采用全域散列和完全散列技术)、不相交集合、任意维数组、高维对称数组。 图论算法(兼容有向图,无向图):广度和深度优先遍历、确定图是否存在回路、拓扑排序、强连通分支、欧拉环(欧拉路径)、最小生成树(Kruskal、Prim)、单源最短路径(3种)、每对顶点间最短路径(2种)、最大流(2种)等等。 代数算法:霍纳法则计算多项式和、矩阵乘法(2种)、方阵的LUP分解、解线性方程组(2种)、矩阵求逆(2种)、求伪逆矩阵(2种)、解正态方程组(2种)、最小二乘估计(2种)、多元最小二乘估计*、快速傅里叶变换、快速傅里叶逆变换、多维快速傅里叶变换、多维快速傅里叶逆变换、快速向量求卷积(单变量多项式乘积)、快速张量求卷积(多变量多项式乘积)、多项式除法*、快速方幂和算法。 序列算法:最长公共子序列、KMP序列匹配*、键值分离排序。 数论算法:大数类(兼容浮点数、整数、与内置类型兼容运算)*、RSA加解密系统*、解同余方程*、孙子定理解同余方程组*、Miller_Rabin素数测试(产生大质数)*、随机数(实数、大数)*、欧几里得算法*。 计算几何算法:确定任意一对线段是否相交*、凸包*、最近点对*。 运筹学:线性规划(单纯形法)*、分配问题*、最优二度子图*、多01背包问题*
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jasmine-Lily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值