【C++之泛型算法】013移除型算法

remvoe()

在C++中,泛型算法是指可以接受任何数据类型的算法,而不仅仅是特定的数据类型。泛型算法是C++标准库中的一个重要概念,用于支持各种数据类型上的通用操作。

remove() 算法是C++标准库中的一个泛型算法,它用于从一个序列中删除特定的元素。该算法不会改变原始序列的大小,而是返回一个新的迭代器,指向新的序列的末尾。

下面是一个使用 remove() 算法的示例代码:

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

int main() {
    std::vector<int> v = {1, 2, 3, 2, 4, 2, 5};

    // 删除所有值为2的元素
    v.erase(std::remove(v.begin(), v.end(), 2), v.end());

    // 打印新的序列
    for (const auto& num : v) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在上面的示例中,我们首先定义了一个包含整数的向量 v。然后,我们使用 remove() 算法删除了所有值为2的元素。注意,remove() 算法本身并不会删除元素,而是将不需要删除的元素移到序列的前面,并返回指向新序列末尾的迭代器。为了实际删除这些元素,我们需要使用 vector 的 erase() 成员函数。

输出将是:1 3 4 5,这是删除了所有值为2的元素后的新序列。

泛型算法 remove() 的声明如下:

template <class ForwardIt, class T>
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value);

其中,ForwardIt 是一个前向迭代器的类型,first 和 last 分别指向要操作的序列的起始和结束位置,value 是要删除的元素的值。该算法返回一个指向新序列末尾的迭代器。

需要注意的是,remove() 算法只是将不需要删除的元素移到序列的前面,而不会改变原始序列的大小。如果要实际删除元素并减少序列的大小,可以使用容器的 erase() 成员函数配合 remove() 算法使用。

remove_if()

std::remove_if() 是C++标准库中的另一个泛型算法,它用于从序列中移除满足特定条件的元素。这个算法会将不满足给定谓词(条件函数)的元素移动到序列的前部,并返回一个指向新的逻辑序列末尾的迭代器。与 std::remove() 不同的是,std::remove_if() 允许你指定一个自定义的条件来决定哪些元素应该被移除。

下面是一个使用 std::remove_if() 的例子,它会从 std::vector 中移除所有偶数:

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

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};

    // 使用 lambda 表达式作为谓词,移除所有偶数
    auto new_end = std::remove_if(v.begin(), v.end(), [](int n) {
        return n % 2 == 0;
    });

    // 实际上删除元素,减少vector的大小
    v.erase(new_end, v.end());

    // 打印修改后的vector
    for (const auto& num : v) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,std::remove_if() 使用了一个 lambda 表达式作为谓词,该表达式检查一个数是否为偶数。所有满足这个条件的元素(即偶数)都会被“移除”(实际上是移动到序列的尾部)。然后,我们使用 std::vector::erase() 方法来实际删除这些元素,并减少 vector 的大小。

std::remove_if() 的声明如下:

template <class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p);

其中,ForwardIt 是一个前向迭代器的类型,first 和 last 分别指向要操作的序列的起始和结束位置,p 是一个一元谓词,它接受一个元素作为参数并返回一个布尔值,指示该元素是否应该被移除。

请注意,std::remove_if() 本身并不会减少容器的大小。要实际删除元素,你需要使用容器的 erase() 方法。如果你使用的是 std::vector 或其他支持 erase() 的容器,你可以像上面的例子那样使用 erase() 方法来减少容器的大小。如果你使用的是不支持 erase() 的容器(如 std::list),你需要使用不同的方法来删除元素。

remove_copy()

std::remove_copy() 是C++标准库中的一个泛型算法,它用于从源序列中复制不满足给定条件的元素到目标序列,并返回指向目标序列末尾的迭代器。与 std::remove() 和 std::remove_if() 不同,std::remove_copy() 并不改变源序列的大小,而是将不满足条件的元素复制到目标序列中,并返回目标序列的末尾迭代器。

下面是一个使用 std::remove_copy() 的例子,这个例子将从一个整数数组中复制所有非偶数元素到另一个数组中:

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

int main() {
    int src[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<int> dest(src, src + sizeof(src) / sizeof(src[0]));

    // 将所有非偶数复制到dest中,并返回目标序列的末尾迭代器
    auto new_end = std::remove_copy_if(src, src + 9, dest.begin(), [](int n) {
        return n % 2 == 0;
    });

    // 调整目标序列的大小以移除末尾的未使用空间
    dest.erase(new_end, dest.end());

    // 打印目标序列
    for (const auto& num : dest) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,我们首先创建了一个源数组 src 和一个与源数组大小相同的目标向量 dest。然后,我们使用 std::remove_copy_if() 将所有非偶数复制到 dest 中,使用了一个 lambda 表达式作为谓词来检查一个数是否为偶数。复制操作完成后,new_end 指向 dest 中新序列的末尾。

最后,我们使用 std::vector::erase() 来调整 dest 的大小,移除末尾未使用的空间。然后,我们打印出目标序列 dest 的内容。

std::remove_copy() 的声明如下:

template <class InputIt, class OutputIt, class UnaryPredicate>
OutputIt remove_copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPredicate p);

其中,InputIt 是源序列的迭代器类型,OutputIt 是目标序列的迭代器类型,first 和 last 定义了源序列的范围,d_first 是目标序列的起始迭代器,p 是一个一元谓词,用于决定哪些元素应该被复制到目标序列中。

请注意,std::remove_copy() 并不保证源序列的顺序不变,也不会删除源序列中的任何元素。如果需要删除源序列中的元素,应该使用 std::remove() 或 std::remove_if() 配合容器的 erase() 方法。

remove_copy_if()

std::remove_copy_if() 是C++标准库中的一个泛型算法,它用于从源序列中复制不满足给定条件的元素到目标序列,并返回指向目标序列末尾的迭代器。与 std::remove_if() 不同,std::remove_copy_if() 并不改变源序列的大小,而是将不满足条件的元素复制到目标序列中,并返回目标序列的末尾迭代器。

下面是一个使用 std::remove_copy_if() 的例子,这个例子将从一个整数数组中复制所有非偶数元素到另一个数组中:

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

int main() {
    int src[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::vector<int> dest;

    // 初始化目标向量,使其足够大以容纳所有元素
    dest.resize(sizeof(src) / sizeof(src[0]));

    // 将所有非偶数复制到dest中,并返回目标序列的末尾迭代器
    auto new_end = std::remove_copy_if(src, src + 9, dest.begin(), [](int n) {
        return n % 2 == 0;
    });

    // 调整目标序列的大小以移除末尾的未使用空间
    dest.resize(std::distance(dest.begin(), new_end));

    // 打印目标序列
    for (const auto& num : dest) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,我们首先创建了一个源数组 src 和一个空的 std::vector dest 作为目标序列。然后,我们使用 std::remove_copy_if() 将所有非偶数复制到 dest 中,使用了一个 lambda 表达式作为谓词来检查一个数是否为偶数。复制操作完成后,new_end 指向 dest 中新序列的末尾。

最后,我们使用 std::vector::resize() 来调整 dest 的大小,移除末尾未使用的空间。然后,我们打印出目标序列 dest 的内容。

std::remove_copy_if() 的声明如下:

template <class InputIt, class OutputIt, class UnaryPredicate>
OutputIt remove_copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPredicate p);

其中,InputIt 是源序列的迭代器类型,OutputIt 是目标序列的迭代器类型,first 和 last 定义了源序列的范围,d_first 是目标序列的起始迭代器,p 是一个一元谓词,用于决定哪些元素应该被复制到目标序列中。

请注意,std::remove_copy_if() 并不保证源序列的顺序不变,也不会删除源序列中的任何元素。如果需要删除源序列中的元素,应该使用 std::remove_if() 配合容器的 erase() 方法。

unique()

在 C++ 标准库中,std::unique 是一个泛型算法,它通常用于删除容器中连续重复的元素。std::unique 的声明如下:

template <class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last);

template <class ForwardIt, class BinaryPredicate>
ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p);

第一个版本接受两个前向迭代器 first 和 last,它们定义了要操作的元素范围。这个版本的 std::unique 使用元素的默认比较操作来判断是否重复。

第二个版本接受一个额外的二元谓词 p,用于自定义元素间的比较逻辑。这个版本的 std::unique 使用提供的谓词 p 来确定元素是否被认为是重复的。

下面是一些使用 std::unique 的例子:
基本用法

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

int main() {
    std::vector<int> v = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};

    // 使用 std::unique 删除连续重复的元素
    auto it = std::unique(v.begin(), v.end());

    // 调整容器大小以移除末尾的未定义元素
    v.erase(it, v.end());

    // 输出结果
    for (const auto& num : v) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,std::unique 删除了向量 v 中的连续重复元素,并且我们通过 v.erase(it, v.end()) 调整了向量的大小,以移除 std::unique 返回的迭代器 it 之后的未定义元素。
使用自定义比较谓词

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

// 自定义比较谓词,判断两个整数是否相等
bool isEqual(const int& a, const int& b) {
    return a == b;
}

int main() {
    std::vector<int> v = {1, 2, 2, 3, 3, 4, 4, 5, 5, 6};

    // 使用自定义比较谓词和 std::unique 删除连续“相等”的元素
    auto it = std::unique(v.begin(), v.end(), isEqual);

    // 调整容器大小
    v.erase(it, v.end());

    // 输出结果
    for (const auto& num : v) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,我们提供了一个自定义的比较谓词 isEqual,它判断两个整数是否相等。std::unique 使用这个谓词来确定哪些元素是重复的,并删除了连续重复的元素。

请注意,std::unique 并不保证容器中元素的唯一性,它只删除连续重复的元素。如果容器中有非连续的重复元素,需要使用其他方法(如 std::sort 和 std::unique 结合使用)来确保整个容器的元素唯一性。

unique_copy()

std::unique_copy 是 C++ 标准库中的一个泛型算法,它类似于 std::unique,但 std::unique_copy 将结果复制到另一个容器中,而不是在原地修改容器。这意味着原始容器的内容不会被改变。

std::unique_copy 的声明如下:

template <class InputIt, class OutputIt>
OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first);

template <class InputIt, class OutputIt, class BinaryPredicate>
OutputIt unique_copy(InputIt first, InputIt last, OutputIt d_first, BinaryPredicate p);

第一个版本接受两个输入迭代器 first 和 last,它们定义了输入序列的范围,以及一个输出迭代器 d_first,它指向用于存储不重复元素的目标容器的起始位置。这个版本的 std::unique_copy 使用元素的默认比较操作来判断是否重复。

第二个版本类似于第一个,但是它还接受一个额外的二元谓词 p,用于自定义元素间的比较逻辑。

下面是一些使用 std::unique_copy 的例子:
基本用法

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

int main() {
    std::vector<int> source = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
    std::vector<int> destination;

    // 将不重复的元素从 source 复制到 destination
    std::unique_copy(source.begin(), source.end(), std::back_inserter(destination));

    // 输出结果
    for (const auto& num : destination) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,std::unique_copy 从 source 向量中复制不重复的元素到 destination 向量中。
使用自定义比较谓词

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

// 自定义比较谓词,判断两个整数是否相等
bool isEqual(const int& a, const int& b) {
    return a == b;
}

int main() {
    std::vector<int> source = {1, 2, 2, 3, 3, 4, 4, 5, 5, 6};
    std::vector<int> destination;

    // 使用自定义比较谓词和 std::unique_copy 复制不重复的元素
    std::unique_copy(source.begin(), source.end(), std::back_inserter(destination), isEqual);

    // 输出结果
    for (const auto& num : destination) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

在这个例子中,我们提供了一个自定义的比较谓词 isEqual,它判断两个整数是否相等。std::unique_copy 使用这个谓词来确定哪些元素是重复的,并只复制不重复的元素到 destination 向量中。

请注意,std::unique_copy 并不保证目标容器 destination 中的元素是排序的。如果需要排序的结果,可以在调用 std::unique_copy 之后对 destination 容器进行排序,如使用 std::sort(destination.begin(), destination.end())。

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

熊猫Devin

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

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

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

打赏作者

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

抵扣说明:

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

余额充值