第10章 泛型算法

大多数算法定义在algorithm中。标准库还在头文件numeric中定义了一组数值泛型算法

练习10.1:头文件algorithm中定义了一个名为count的函数,它类似find,接受一对迭代器和一个值作为参数。count返回给定值在序列中出现的次数。编写程序,读取int序列存入vector中,打印有多少个元素的值等于给定值,

#include 
#include 
#include 

using namespace std;

int main()
{
    vector nums = {123,456,789,123,456,789,1};
    cout << count(nums.cbegin(), nums.cend(), 123) << endl;

    return 0;
}

练习10.3:用accumulate求一个vector中的元素之和

#include 
#include 
#include 

using namespace std;

int main()
{
    vector nums = {1,2,3,4,5,6};
    cout << accumulate(nums.cbegin(), nums.cend(), 0);
    return 0;
}

练习10.9:实现你自己的elimDups。测试你的程序,分别在读取输入后、调用unique后以及调用erase后打印vector的内容。

void elimDups(vector & words)
{
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());
    words.erase(end_unique, words.end());
}

练习10.11:编写程序,使用stable_sort和isShorter将传递给你的elimDups版本的vector排序。打印vector的内容,验证你程序的正确性

#include 
#include 
#include 

using namespace std;
bool isShorter(const string &s1, const string &s2)
{
    return s1.size() < s2.size();
}
void elimDups(vector & words);
int main()
{
    vector words = {"the", "quick", "red", "fox", "jumps", "over",
                            "the", "slow", "red", "turtle"};
    elimDups(words);
    stable_sort(words.begin(), words.end(), isShorter);
    for (auto i : words)
        cout << i << " ";
    
    return 0;
}

void elimDups(vector & words)
{
    sort(words.begin(), words.end());
    auto end_unique = unique(words.begin(), words.end());
    words.erase(end_unique, words.end());
}

练习10.13:标准库定义了名为partition的算法,它接受一个谓词,对容器内容进行划分,使得谓词为true的值会排在容器的前半部分,而未日次false的值会在后半部分。算法返回一个迭代器指向最后一个使谓词位true的元素之后的位置。编写一个函数,接受string,返回bool,指出string是否有5个或更多字符。使用此函数划分words打印长度大于等于5的元素,

#include 
#include 
#include 
#include 

using namespace std;

bool compareWords(const string &);

int main()
{
    vector words = {"the", "quick", "red", "fox", "jumps", "over",
                            "the", "slow", "red", "turtle"};
    auto end = partition(words.begin(), words.end(), compareWords);
    for (auto i = words.begin(); i != end; ++i)
    {
        cout << *i << " ";
    }

    return 0;
}

bool compareWords(const string & words)
{
    return words.size() > 4;
}

lambda

lambda表达式形式:
[capture list] (parameter list) -> return type { function body}

  • 捕获列表只用于局部非静态变量。
  • 可以直接使用局部静态变量和外部变量

练习10.14:编写一个lambda,接受两个int,返回他们的和。

#include 

using namespace std;
int main()
{
    int a = 5, b = 4;
    auto f = [](const int a, const int b) {return a + b;};
    cout << f(a, b) << endl;
}

练习10.15:编写一个lambda,捕获它所在函数的int,并接受一个int参数。lambda应该返回捕获的int和int参数的和。

#include 

using namespace std;
int main()
{
    int a = 5, b = 4;
    auto f = [a](const int b) {return a + b;};
    cout << f(b) << endl;
}

从写biggies用partition代替find_if

void biggies(vector &words, vector::size_type sz)
{
    elimDups(words);
    stable_sort(words.begin(), words.end(),
                        [](const string &a, const string &b)
                            { return a.size() < b.size();});
    auto wz = partition(words.begin(), words.end(),
                            [sz](string &a)
                                { return a.size() < sz;});
    for_each( wz, words.end(),
                [](const string &a)
                    {cout << a << " ";});
    cout << endl;
}

在创建lambda的时候捕获列表就保存了捕获的值
修改捕获列表的值必须使用mutable
auto f = [&a] () mutable {return ++a;};
返回其他类型使用尾置返回类型

可以使用bind代替lambda
引用 ref bind(print, ref(os), _1, ' ')
placeholders命名空间
using namespace std::placeholders;

练习10.22:重写统计长度小于等于5的单词数量的程序。使用函数代替lambda;

#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace std::placeholders;

void biggies(vector &words, vector::size_type sz);
void elimDups(vector &words);
bool check6(const string &a, string::size_type sz);  //bind

int main()
{
    vector words = {"the", "quick", "red", "fox", "jumps", "over",
                            "the", "slow", "red", "turtle"};
    biggies(words, 5);
}

void elimDups(vector &words)
{
    sort(words.begin(), words.end());
    auto no_unique = unique(words.begin(), words.end());
    words.erase(no_unique, words.end());
}

void biggies(vector &words, vector::size_type sz)
{
    elimDups(words);
    stable_sort(words.begin(), words.end(),
                        [](const string &a, const string &b)
                            { return a.size() < b.size();});
    auto wz = find_if(words.begin(), words.end(), 
                        bind(check6, _1, sz));
    for_each(words.begin(), wz,
                [](const string &a)
                    {cout << a << " ";});
    cout << endl;
}

bool check6(const string &a, string::size_type sz)
{
    return a.size() > sz;
}

练习10.23:bind接受几个参数?
auto newCallable = bind(callable, arg_list);


image.png

练习10.26:解释三种插入迭代器的不同之处

  • back_inserter:创建使用push_back的迭代器
  • front_inserter创建一个使用push_front的迭代器
  • inserter:创建一个使用insert的迭代器。此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。

练习10.27:使用unique_copy函数将不重复的字母copy到一个初始化为空的list中

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

int main()
{
    vector words = {"the", "quick", "red", "fox", "jumps", "over",
                        "the", "slow", "red", "turtle"};
    list wwww;
    sort(words.begin(), words.end());
    unique_copy(words.cbegin(), words.cend(), inserter(wwww, wwww.begin()));
    for (auto i : words)
        cout << i << " ";
    cout << endl;
    for (auto i : wwww)
        cout << i << " ";
    cout << endl;

    return 0;
}

练习10.28:一个vector中保存1-9用三种迭代器copy到三种不同的容器


练习10.29:编写程序,使用流迭代器读取一个文本文件,存入一个vector中的string里

#include 
#include 
#include 
#include 
#include 

using namespace std;

int main()
{
    ifstream in("1.txt");
    istream_iterator str_it(in);
    istream_iterator eof;
    vector str(str_it, eof);

    ostream_iterator out_iter(cout, " ");
    copy(str.cbegin(), str.cend(), out_iter);
    cout << endl;

    return 0;
}

练习10.30:使用流迭代器、sort和copy从标准输入读取一个整数序列,将其排序,并将结构写到标准输出

#include 
#include 
#include 
#include 
#include 

using namespace std;

int main()
{
    istream_iterator in_iter(cin);
    istream_iterator eof;
    vector nums(in_iter, eof);
    sort(nums.begin(), nums.end());
    ostream_iterator out_iter(cout, " ");
    copy(nums.cbegin(), nums.cend(), out_iter);

    return 0;
}

练习10.34:使用reverse_iterator逆序打印一个vector

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    vector vec = {1,2,3,4,5,6,7,8};
    for (auto r_iter = vec.crbegin(); 
                r_iter != vec.crend();
                ++r_iter)
        cout << *r_iter << endl;
    return 0;
}

练习10.37:给定一个包含10个元素的vector,将3-7之间的元素逆序拷贝到list中

#include 
#include 
#include 

using namespace std;
int main()
{
    vector num = {1,2,3,4,5,6,7,8,9,0};
    list nums(num.crbegin() + 3, num.crend() - 2);
    for (auto i : nums)
        cout << i << " ";
    cout << endl;

    return 0;
}

练习10.38:列出5个迭代器类别,以及每类迭代器所支持的操作。
输入迭代器:只读,不写;单遍扫描,只能递增
输出迭代器:只写,不读:单遍扫描,只能递增
前向迭代器:可读写;多遍扫描,只能递增
双向迭代器:可读写;多遍扫描,可递增递减
随机访问迭代器:可读写,多遍扫描,支持全部迭代器运算

你可能感兴趣的:(第10章 泛型算法)