C + + generic algorithm

Posted by nawhaley2265 on Fri, 07 Jan 2022 10:36:11 +0100

generic algorithm

Generic algorithms are some algorithms defined in STL library. These algorithms can operate various data types with one interface, so they become generic algorithms. Most algorithms are defined in the header files algorithm and numeric. It means that various types of algorithms can be operated with one interface, which is a generic algorithm.

Generic algorithms are divided into two categories: read-only algorithms and algorithms that modify the original container.
Read only algorithms include find, accumulate, etc.
Modification algorithms include replace, fill, etc.

accumulate

    vector<int> nvec = {1, 2, 3, 4, 5, 6, 7};
    //Call accumulate, the initial value of sum is 0, and the accumulation result is written to sum
    auto sum = accumulate(nvec.begin(), nvec.end(), 0);
    cout << "sum is " << sum << endl;
    list<string> strlist = {"hello", "zack", "good", "idea"};
    string stradd = accumulate(strlist.begin(), strlist.end(), string(""));
    cout << "str add result is " << stradd << endl;

Calculate takes the third parameter as the starting point of summation, which implies a programming assumption that the operation of adding element types to the types of and must be feasible. That is, the type of the element in the sequence must match or be convertible to the type of the third parameter. In the above example, the element in vec can be int, or double, long, long, or any other type that can be added to int. Since string defines the + operator, we can connect all string elements in the vector by calling calculate
Program output

sum is 28
str add result is hellozackgoodidea

equal

Generic algorithms have algorithms that operate on two sequences. For example, equal is to compare whether the elements in the two sequences have equal values. If each element in the first sequence is equal to the elements in the second sequence, it returns true, otherwise it returns false.

 bool bequa = equal(strlist.begin(), strlist.end(), strlist2.begin());
    if (bequa)
    {
        cout << "strlist is equal to strlist2" << endl;
    }
    else
    {
        cout << "strlist is not equal to strlist2" << endl;
    }

The above code compares strlist and strlist2. Remember that the length of strlist2 should be greater than or equal to strlist, otherwise the program will have problems. Algorithms that accept only a single iterator to represent the second sequence assume that the second sequence is at least as long as the first sequence.

fill

You can modify the value of the container through the fill algorithm, which accepts a pair of iterators to represent a range and a value as the third parameter. Fill assigns the given value to each element in the input sequence.

    vector<int> nvec2 = {1, 2, 3, 4};
    //Set all elements in nvec2 to 0
    fill(nvec2.begin(), nvec2.end(), 0);
    //Set the first half of nvec2 to 10
    fill(nvec2.begin(), nvec2.begin() + nvec2.size() / 2, 10);

Similar to fill_n function, which accepts a single iterator, a count value and a value.

    vector<int> vec;
    fill_n(vec.begin(), vec.size(), 0);

The following call to fill will cause the program to crash, because the size of vec3 is 0. If fill wants to write 10 zeros to vec3, it will cause out of bounds crash.

//Empty vector
vector<int> vec3;
// Disaster, modify 10 nonexistent elements in vec3
fill_n(vec3.begin(),10,0);

back_inserter

fill_n if the number of passes is larger than the size of the container, it will cause a crash. To prevent similar problems, stl introduces back_inserter. back_ The inserter accepts a reference to the container and returns an insert iterator bound to the container. When we assign a value through this iterator, the assignment operator calls push_back adds an element with a given value to the container:

    //Empty vector
    vector<int> nvec4;
    // back_ The inserter binds nvec4 and returns the iterator
    auto iter = back_inserter(nvec4);
    //The assignment to the iterator is to insert an element into nvec
    *iter = 2;
    *iter = 4;
    for (auto it = nvec4.begin(); it != nvec4.end(); it++)
    {
        cout << *it << " ";
    }

The program prints out 2 and 4 in turn
We often use back_ Insert to create an iterator to be used as the destination of the algorithm. For example:

    //Empty vector
    vector<int> nvec5;
    // back_ The inserter binds nvec5 and returns the iterator
    auto iter5 = back_inserter(nvec5);
    //Add 10 elements to write to nvec5
    fill_n(iter5, 10, 0);

copy

The copy algorithm is another algorithm that writes data to the elements in the output sequence pointed to by the destination iterator. This algorithm accepts three iterators. The first two represent an input range and the third represents the starting position of the target sequence. This algorithm copies the elements in the input range to the destination sequence. The destination sequence passed to copy must contain at least as many elements as the input sequence.

    int a1[] = {0, 1, 2, 3, 4, 5, 6};
    constexpr int nszie = sizeof(a1) / sizeof(int);
    int a2[nszie];
    //copy a1 content to a2
    copy(begin(a1), end(a1), a2);

replace

We can replace a value in the original container with a new value

    vector<int> nvec6 = {1, 2, 3, 4};
    //Set all elements in nvec6 with 3 to 32
    replace(nvec6.begin(), nvec6.end(), 3, 32);

If the original container data is retained, you can use back_ The inserter binds a new container and uses replace_copy completes the copy and replace operations

    //Raw data list
    list<int> ilist = {0, 1, 2, 3, 4, 5};
    //Empty vector
    vector<int> rcpvec;
    //copy the data in ilist to rcpvec, but replace 0 with 42
    replace_copy(ilist.begin(), ilist.end(), back_inserter(rcpvec), 0, 42);

unique and sort

We implement a function to sort the words in the vector and remove the repeated words.
We can use the sort function to sort the words in the vector first, and then use unique to remove the duplicate words. Unique returns the iterator of the last element that is not repeated. Unique ensures that the first n elements in the container are not repeated, and the beginning of n+1 is repeated, so we can use erase to delete the contents after n+1 elements.

    vector<string> words = {"good", "idea", "zack", "lucy", "good", "idea"};
    //First sort the words in words
    sort(words.begin(), words.end());
    // unique moves elements, placing non repeating elements in the front and repeating elements in the back
    // unique returns the position of the last element that is not repeated
    const auto uniqueiter = unique(words.begin(), words.end());
    //Call erase to delete duplicate elements
    words.erase(uniqueiter, words.end());

Print out words. You can see that words becomes {good, idea, Lucy, Zack}

Topics: C++