Day 31 C++ STL Common Algorithms (Part 2)

Article Directory

Common Copy and Replace Algorithms

copy—copies the specified range of elements in the container to another container

function prototype
  • copy(iterator beg, iterator end, iterator dest);

    // Find the element by value, if found, return the iterator at the specified position, if not found, return the end iterator position

    // beg starts the iterator

    // end end iterator

    // dest target starting iterator

Note - When using the copy algorithm to copy, the target container must open up space in advance
example
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> source {1, 2, 3, 4, 5};
    std::vector<int> destination(5);  // 提前开辟目标容器空间

    std::copy(source.begin(), source.end(), destination.begin());

    // 输出目标容器中的内容
    for (auto i : destination) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is: 1 2 3 4 5

In the above example, we first created a source container source, which contains some integers. Then, we created a destination container of the same size as the source container, and allocated space ahead of time.

Next, we use the std::copy algorithm to copy the elements in the source container to the destination container. The copy operation is implemented by passing the iterators source.begin() and source.end() of the source container and the start iterator destination.begin() of the destination container as parameters.

Finally, traverse the target container and print the elements in it

replace - modify the first old element in the specified range in the container to a new element

function prototype
  • replace(iterator beg, iterator end, oldvalue, newvalue);

    // Replace the old elements in the interval with new elements

    // beg starts the iterator

    // end end iterator

    // oldvalue old element

    // newvalue new element

Note - replace will only replace the first old element in the range that satisfies the condition
example
#include <iostream>
#include <vector>
#include <algorithm>

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

    std::replace(vec.begin(), vec.end(), 3, 9);

    // 输出修改后的容器内容
    for (auto i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:
1 2 9 4 5

In the above example, we first created an integer vector vec containing some integers. We then replace the old element 3 in the container with the new element 9 using the std::replace algorithm.

The replacement operation is implemented by passing the container's start iterator vec.begin() and end iterator vec.end() as parameters, and the old element 3 and the new element 9 to be replaced.

Finally, we traverse the container and print the elements in it, and we can see that the replaced elements have been modified into new elements.

replace_if - modify all old elements to new elements within the specified range

function prototype
  • **replace_if(iterator beg, iterator end, _pred, newvalue); **

    // Replace elements according to the conditions, and replace the elements that meet the conditions with the specified elements

    // beg starts the iterator

    // end end iterator

    // _pred 谓词, the predicate function is a function that returns a Boolean value to determine whether an element satisfies a certain condition.

    // Note that the predicate is a functor that returns bool. It is a predicate, a class, not a function, but it can be used as a function. //
    Therefore, the functor can be used to flexibly filter the satisfied conditions

    // The new element replaced by newvalue

Note - replace will replace all old elements in the range that meet the condition

Example:

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

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

    std::replace_if(vec.begin(), vec.end(), [](int num){ return num == 3; }, 9);

    // 输出修改后的容器内容
    for (auto i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:
1 2 9 4 5

In this example, we use an anonymous lambda function as a predicate function to determine whether the element needs to be replaced. The lambda function accepts an integer parameter num and returns a bool value to determine whether the integer is equal to 3. If it is equal to 3, replace it with the new element 9.

By using a lambda function as a predicate function, we can customize the replacement condition. In the above example, we used an element equal to 3 as the condition for replacement.

It should be noted that the replace_if function will only replace the first element that meets the condition. If you want to replace all elements that meet the condition, you can consider using std::replace_copy_if or a custom loop for processing.

swap - swaps the elements of two containers

function prototype
  • swap(container c1, container c2);

    // Swap the elements of the two containers

    // c1 container 1

    // c2 container 2

Note——When swapping containers, note that the swapped containers must be of the same type

Swapping containers of different types will result in compilation errors.

type to match

The container types to be exchanged must be the same, or satisfy the conditions for implicit conversion. For example, two std::vector<int>can be swapped directly, but not between std::vector<int>and .std::vector<double>

state of the container

When swapping containers, make sure that the containers are in a valid state, i.e. they should not be moved, freed or destroyed. Otherwise, the swap operation may result in undefined behavior.

iterator invalidation

After swapping containers, the iterators in the original container will be invalidated. If you have other code that depends on these iterators, you need to be careful not to use invalid iterators.

Container size and memory overhead

Swapping containers actually swaps their internal data structures, which means copying or moving elements is involved. If the size of the container is large, the swap operation may incur significant memory overhead and performance loss.

exception safety

Swapping containers may cause exceptions, so before swapping operations, consider exception safety and take appropriate measures to handle exceptions to ensure that the program can execute normally.

example
#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);

    // 输出交换后的vec1
    std::cout << "vec1: ";
    for (auto i : vec1) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    // 输出交换后的vec2
    std::cout << "vec2: ";
    for (auto i : vec2) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:
vec1: 4 5 6
vec2: 1 2 3

In this example, we create two vector containers vec1 and vec2.
Then, swap the elements of the two containers by calling the swap function. Eventually
, the elements in vec1 become 4, 5, 6, and the elements in vec2 become 1, 2, 3.

Common Arithmetic Generation Algorithms

Note—the arithmetic generation algorithm is a small algorithm, and the header file included when using it is#include <numeric>

accumulate - Calculate the cumulative sum of the container elements in the range

function prototype
  • accumulate(iterator beg, iterator end, value);

    // Calculate the cumulative sum of the container elements

    // beg starts the iterator

    // end end iterator

    // value start value
    // start value value is optional, if this parameter is not provided, the default start value will be the value of the first element in the container. (see example below)

Note - If the container is empty and no start value argument is provided, calling the accumulate function results in undefined behavior

Therefore, when using the accumulate function, it is recommended to check whether the container is not empty before accumulating, or provide an explicit starting value parameter.

example
#include <iostream>
#include <vector>
#include <numeric>

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

    int sum = std::accumulate(vec.begin(), vec.end());

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

The output is:
Sum: 15

In this example, we call the accumulate function to calculate the cumulative sum of the elements in the container vec, but do not provide a starting value argument. Since no starting value is specified, the accumulate function will use the first element in the container as the starting value for accumulation.

So the cumulative sum is still 15 according to the container vec in the example.

fill - used to set the elements in the specified range to the given value

function prototype
  • fill(iterator beg, iterator end, value);

    // fill the container with elements

    // beg starts the iterator

    // end end iterator

    // value filled value

Note - the fill function will fill all elements within the pointed range with the given value, and the original value will be overwritten.
example
#include <iostream>
#include <vector>
#include <algorithm>

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

    std::fill(vec.begin(), vec.end(), 10);

    // 输出填充后的向量
    std::cout << "Filled Vector: ";
    for (auto i : vec) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:

Filled Vector: 10 10 10 10 10
In this example, we have a vector vec containing initial values, which contains the numbers 1 to 5. Then, we use the fill function to fill all elements in the container vec with 10.

The final output shows that the elements in the original vector have been overwritten and all become 10, 10, 10, 10, 10.

Therefore, it should be noted that when using the fill function, if you want to retain the value of the original element and only fill some elements within the specified range, you can use a more flexible method, such as a combination of iterators and algorithms to achieve partial filling .

Common Set Algorithms

set_intersection - find the intersection of two containers

set_intersectionFunctions are often used to compute the intersection of two sorted sets.
However, it can actually be used with any sequence container that supports random access, not just collections.

function prototype
  • set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
    // beg1 container 1 start iterator
    // end1 container 1 end iterator
    // beg2 container 2 start iterator
    // end2 container 2 end iterator
    // dest destination container start iterator
Summarize
  • The two sets to be intersected must be ordered sequences
  • The target container needs to take the small value from the two containers to open up space
  • The return value of set_intersection is the position of the last element in the intersection

Example:

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

int main() {
    std::vector<int> vec1 {1, 2, 3, 4, 5};
    std::vector<int> vec2 {3, 4, 5, 6, 7};

    std::vector<int> intersection(std::min(vec1.size(), vec2.size()));

    auto it = std::set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), intersection.begin());

    // 输出交集中的元素
    std::cout << "Intersection: ";
    for (auto i = intersection.begin(); i != it; ++i) {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:
Intersection: 3 4 5

In this example, we have two ordered vectors vec1 and vec2 each containing different integers. We need to find the intersection of these two vectors.

First, we create a target container intersection whose size is the smaller of the two input containers.

Then, use the set_intersection function to copy the intersection in the two input containers into the destination container intersection. The set_intersection function accepts five parameters, which are the start and end iterators of the two input containers, and the start iterator of the target container. This way, the elements in the intersection are copied into the destination container.

Finally, we iterate over the elements in the target container and output the values ​​in the intersection.

set_union - Find the union of two sets

function prototype
  • set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

    // beg1 container 1 start iterator
    // end1 container 1 end iterator
    // beg2 container 2 start iterator
    // end2 container 2 end iterator
    // dest destination container start iterator

Summary (similar to set_intersection)
  • The ordered sequence necessary to find the union of two sets
  • The target container needs to add two containers to open up space
  • The return value of set_union is the position of the last element in the union
example
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec1 {1, 2, 3, 4, 5};
    std::vector<int> vec2 {3, 4, 5, 6, 7};

    std::vector<int> unionSet(vec1.size() + vec2.size());

    auto it = std::set_union(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), unionSet.begin());

    // 输出并集中的元素
    std::cout << "Union: ";
    for (auto i = unionSet.begin(); i != it; ++i) {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:
Union: 1 2 3 4 5 6 7

In this example, we have two ordered vectors vec1 and vec2 each containing different integers. We need to find the union of these two vectors.

First, we create a target container unionSet whose size is the total size of the two input containers.

Then, use the set_union function to copy the union of the two input containers into the destination container unionSet.
The set_union function accepts five parameters, which are the start and end iterators of the two input containers, and the start iterator of the target container. This way, the elements in the union are copied into the destination container.

Finally, we iterate over the elements in the target container and output the unioned values.

set_difference——Find the difference of two sets

function prototype
  • set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);

    // beg1 container 1 start iterator
    // end1 container 1 end iterator
    // beg2 container 2 start iterator
    // end2 container 2 end iterator
    // dest destination container start iterator

summary (almost)
  • The ordered sequence necessary for two sets to be subtracted
  • The target container needs to take the larger value from the two containers to open up space
  • The return value of set_difference is the position of the last element in the difference set

Example:

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

int main() {
    std::vector<int> vec1 {1, 2, 3, 4, 5};
    std::vector<int> vec2 {3, 4, 5, 6, 7};

    std::vector<int> difference(std::max(vec1.size(), vec2.size()));

    auto it = std::set_difference(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), difference.begin());

    // 输出差集中的元素
    std::cout << "Difference: ";
    for (auto i = difference.begin(); i != it; ++i) {
        std::cout << *i << " ";
    }
    std::cout << std::endl;

    return 0;
}

The output is:
Difference: 1 2

In this example, we have two ordered vectors vec1 and vec2 each containing different integers. We need to find the difference of these two vectors.

First, we create a target container difference whose size is the larger of the two input containers.

Then, use the set_difference function to copy the difference from the two input containers into the destination container difference.
The set_difference function accepts five parameters, which are the start and end iterators of the two input containers, and the start iterator of the target container. In this way, the elements in the difference set are copied into the destination container.

Finally, we iterate over the elements in the target container and output the value in the difference.

Guess you like

Origin blog.csdn.net/m0_74921567/article/details/132335483