C++之STL的algorithm(4)之拷贝相关算法(copy、replace、swap)整理

admin2024-04-03  0

C++之STL的algorithm(4)之拷贝相关算法(copy、replace、swap)整理

注:整理一些突然学到的C++知识,随时mark一下
例如:忘记的关键字用法,新关键字,新数据结构


C++ 的查找算法整理

  • C++之STL的algorithm(4)之拷贝相关算法(copy、replace、swap)整理
  • 一、拷贝替换算法
    • 1、 copy 算法
    • 2、replace 算法
    • 3、 replace_if 算法
  • 二、交换算法
    • 1、swap 算法
    • 2、map如何实现 swap
  • 总结

提示:本文为 C++ 中copy、replace、swap 的写法和举例


一、拷贝替换算法

  详细解释<algorithm>头文件中各个查找算法的参数列表和返回值,然后给出使用vector、map、set的例子。需要注意的是,并非所有的STL算法都适用于上述所有类型的容器,如map和set是基于关联的数据结构,而vector则是基于序列的数据结构。

1、 copy 算法

参数:

beg:源范围起始迭代器。
end:源范围结束迭代器。
dest:目标容器起始迭代器。
返回值:

返回目标容器中最后一个拷贝元素之后的位置的迭代器。

例子:

#include <iostream>  
#include <vector>  
#include <algorithm>  
  
int main() {  
    std::vector<int> source = {1, 2, 3, 4, 5};  
    std::vector<int> destination(5); // 预先分配空间  
  
    // 使用copy算法将source的元素拷贝到destination  
    std::copy(source.begin(), source.end(), destination.begin());  
  
    // 输出destination  
    for (int i : destination) {  
        std::cout << i << ' ';  
    }  
  
    return 0;  
}

对于map和set,copy算法并不直接适用,因为它们不是简单的序列容器。如果你需要复制map或set中的元素,通常使用循环遍历或者范围基于的for循环。

2、replace 算法

参数:

beg:源范围起始迭代器。
end:源范围结束迭代器。
oldvalue:要被替换的旧元素值。
newvalue:新元素值。

返回值:

无返回值,但会修改源容器中的元素。

例子:

#include <iostream>  
#include <vector>  
#include <algorithm>  
  
int main() {  
    std::vector<int> vec = {1, 2, 3, 2, 5};  
  
    // 使用replace算法将vec中所有的2替换为10  
    std::replace(vec.begin(), vec.end(), 2, 10);  
  
    // 输出vec  
    for (int i : vec) {  
        std::cout << i << ' ';  
    }  
  
    return 0;  
}

对于map和set,replace算法也不适用,因为它们是根据键值对存储的,且不允许重复。如果需要替换map或set中的元素,你需要先找到该元素,然后修改它。

3、 replace_if 算法

参数:

beg:源范围起始迭代器。
end:源范围结束迭代器。
_callback:一个谓词(返回bool类型的函数对象或lambda表达式),用于判断哪些元素需要被替换。
newvalue:新元素值。

返回值:

无返回值,但会修改源容器中的元素。

例子:

#include <iostream>  
#include <vector>  
#include <algorithm>  
  
int main() {  
    std::vector<int> vec = {1, 2, 3, 4, 5};  
  
    // 使用replace_if算法将vec中所有偶数替换为10  
    std::replace_if(vec.begin(), vec.end(), [](int i){ return i % 2 == 0; }, 10);  
  
    // 输出vec  
    for (int i : vec) {  
        std::cout << i << ' ';  
    }  
  
    return 0;  
}

对于map和set,同样地,replace_if算法不直接适用。如果需要基于条件替换map或set中的元素,你需要遍历容器,并对每个元素应用条件判断。

二、交换算法

1、swap 算法

参数:

c1:第一个容器。
c2:第二个容器。

返回值:

无返回值,但会交换两个容器的元素。

例子:

对于vector,swap算法可以直接用来交换两个容器的所有元素:

#include <iostream>  
#include <vector>  
#include <algorithm>  
  
int main() {  
    std::vector<int> vec1 = {1, 2, 3};  
    std::vector<int> vec2 = {4, 5, 6};  
  
    // 使用swap算法交换vec1和vec2的元素  
    std::swap(vec1, vec2);  
  
    // 输出vec1和vec2  
    for (int i : vec1) {  
        std::cout << i << ' ';  
    }  
    std::cout << std::endl;  
    for (int i : vec2) {  
        std::cout << i << ' ';  
    }  
  
    return 0;  
}

然而,对于map和set,情况也是不适用该算法

2、map如何实现 swap

因为map和set的底层实现涉及到复杂的关联数据结构(如红黑树),它们没有提供直接交换两个容器内容的成员函数或算法。如果你需要交换两个map或set的内容,你需要自己实现这个过程,例如通过遍历一个容器并将元素插入到另一个容器中,同时清空第一个容器。

这里是一个简单的示例来展示如何交换两个map的内容:

#include <iostream>  
#include <map>  
  
void swap_maps(std::map<int, int>& m1, std::map<int, int>& m2) {  
    // 先将m1的元素插入到m2中  
    for (const auto& kv : m1) {  
        m2[kv.first] = kv.second;  
    }  
    // 清空m1  
    m1.clear();  
    // 将m2的元素(原本m1的元素)移动回m1  
    for (const auto& kv : m2) {  
        m1[kv.first] = kv.second;  
    }  
    // 清空m2  
    m2.clear();  
}  
  
int main() {  
    std::map<int, int> map1 = {{1, 10}, {2, 20}, {3, 30}};  
    std::map<int, int> map2 = {{4, 40}, {5, 50}, {6, 60}};  
  
    // 调用自定义的swap_maps函数交换map1和map2的内容  
    swap_maps(map1, map2);  
  
    // 输出map1和map2  
    for (const auto& kv : map1) {  
        std::cout << kv.first << ": " << kv.second << std::endl;  
    }  
    for (const auto& kv : map2) {  
        std::cout << kv.first << ": " << kv.second << std::endl;  
    }  
  
    return 0;  
}

请注意,上面的swap_maps函数是一个简单的实现,它假设两个map原本没有相同的键。如果可能存在相同的键,你需要先决定如何处理键冲突(比如保留一个,合并值,还是抛出异常)。

总结

包括copy、replace、replace_if和swap

  1. std::copy
template<class InputIt, class OutputIt>  
OutputIt copy(InputIt first, InputIt last, OutputIt d_first);

first, last: 输入序列的开始和结束迭代器。
d_first: 输出序列的起始迭代器。
std::vector<int> src = {1, 2, 3, 4, 5};  
std::vector<int> dst(src.size());  
std::copy(src.begin(), src.end(), dst.begin());
  1. std::replace
template<class ForwardIt, class T, class U>  
void replace(ForwardIt first, ForwardIt last, const T& old_value, const U& new_value);
first, last: 序列的开始和结束迭代器。
old_value: 要被替换的值。
new_value: 替换成的新值。
std::vector<int> vec = {1, 2, 3, 2, 4};  
std::replace(vec.begin(), vec.end(), 2, 5);
  1. std::replace_if
template<class ForwardIt, class UnaryPredicate, class T>  
void replace_if(ForwardIt first, ForwardIt last, UnaryPredicate p, const T& new_value);
first, last: 序列的开始和结束迭代器。
p: 一元谓词,用于判断哪些元素需要被替换。
new_value: 替换成的新值。
std::vector<int> vec = {1, 2, 3, 4, 5};  
std::replace_if(vec.begin(), vec.end(), [](int n){ return n % 2 == 0; }, -1);
  1. std::swap
template<class T>  
void swap(T& a, T& b) noexcept(noexcept(a = std::move(b)) && noexcept(b = std::move(a)));
a, b: 要交换的两个对象的引用。

或者对于STL容器,也可以直接使用swap成员函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!