Summary of STL interval member function and interval algorithm

  • 2020-04-02 03:08:37
  • OfStack

The interval member function and interval algorithm of the substitutable loop are summarized here.

The advantage of using interval member functions over single element traversal operations is that:
1) fewer function calls
2) less element movement
3) less memory allocation

Interval algorithm should also be used when interval member function is not applicable. At least, it is simpler, more effective and less error-prone than handwritten loop.

Interval member function

Interval structure

Standard containers all support interval constructors:


container::container(InputIterator begin, //The starting point of the interval is
                  InputIterator end); //The end of the interval is

Such as:


int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);

Above is the common usage of c++98. In c++ 11, vector can be initialized directly:


std::vector<int> second ={10, 20, 30, 30, 20, 10, 10, 20}; 

Or:


std::vector<int> second ({10, 20, 30, 30, 20, 10, 10, 20});  

Interval insert

The standard sequence container provides this form of insert:


void container::insert(iterator position, //Interval insertion position
                    InputIterator begin, //The starting point of the insertion interval is
                    InputIterator end); //The end of the insertion interval is

Such as:


int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector;
myvector.push_back(100);
myvector.insert(myvector.begin(),myints,myints+8); //10 20 30 30 20 10 10 20 100

The associative container also supports interval insertion, but since its position after insertion is determined by its comparison function, there is no such parameter as the position of interval insertion.

Interval to delete

Erase provided by the standard sequence container:

Iterator container::erase(iterator begin, iterator end);

The erase provided by the standard associated container for c++98 is:

Void container::erase(iterator begin, iterator end);

After the sequence container calls erase, it returns an iterator (the next one for the deleted element),
The erasing of the associated container does not return to the iterator.

This distinction was finally reconciled in c++11; In c++11, calling erase on the associated container returns an iterator (pointing to the next element to be deleted);

Iterator container::erase(const_iterator first, const_iterator last);

The interval assignment

All standard containers provide member functions for interval assignment:

Void container::assign(InputIterator begin, InputIterator end);
This function assigns values to containers, replaces existing values, and allocates space as needed.
The difference with copy() algorithm is that it does not need to allocate space in advance and has higher performance.


int myints[]={10,20,30,40,50,60,70};
std::vector<int> myvector;
myvector.assign(myints,myints+7);

General interval algorithm

Iteration on the for_each interval

For_each: traverses, performing an action on each element;
C++98 only supports the most primitive for loop, and many languages (Java, python, etc.) implement the foreach interval iteration syntax, which makes C++ programmers long hungry.
In the era without foreach interval iteration, we can use the for_each() algorithm instead:

Example: add 5 to each element:


void myfunction (int& i) {
    i += 5;
}
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
for_each(myvector.begin(),myvector.end(),myfunction); //15 25 35

Interval iteration is added in c++11, which makes our dependence on for_each less and easier to use:


for(auto &i : myvector )
{
    i+=5;
}

After the transform() interval is iterated, the new value is saved elsewhere

After performing an operation on each element in the interval, the modified value is written to the new interval.
Think of this as the for_each() algorithm without modifying the version of the original interval;
Again, the for_each example:


int addfunction(int i ){
    return i+5;
}
void output (int i) {  // output function
    std::cout << ' ' << i;
}
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
std::vector<int> bvector;
bvector.resize(myvector.size());
transform(myvector.begin(),myvector.end(),bvector.begin(),addfunction);
//O < br / > for_each(bvector.begin(),bvector.end(),output); //bvector: 15 25 35

Copy () interval copy

Interval replication, generally used for data transfer between multiple containers;
This algorithm is widely used. In fact, many scenarios using copy can be replaced by interval member function (also recommended).

Example: copy array to vector:


int myints[]={10,20,30,40,50,60,70};
std::vector<int> myvector (7);
std::copy ( myints, myints+7, myvector.begin() );

Fill () interval

Fill the interval repeatedly with an element;
This algorithm is used less frequently;
Example: fill the first four elements of a vector with 5:


std::vector<int> myvector (8);                       // myvector: 0 0 0 0 0 0 0 0
std::fill (myvector.begin(),myvector.begin()+4,5);   // myvector: 5 5 5 5 0 0 0 0

Replace () interval

Traverse the interval and replace the value:
Example: replace all 20 in the following interval with 99:


int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
std::replace (myvector.begin(), myvector.end(), 20, 99); // 10 99 30 30 99 10 10 99

A more complex version (using a functor) of replace_if
Example: replace all values greater than 20 in the following interval with 99:


bool bigerThen20 (int i) { return i > 20; }
int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
std::replace_if (myvector.begin(), myvector.end(), bigerThen20, 99); //10 20 99 99 20 10 10 20

Because of the use of functors, it's also easy to implement for_each() through replace_if;

Remove () interval

Deletes the specified element from the interval;


int myints[] = { 10, 20, 30, 30, 20, 10, 10, 20 };
std::vector<int> myvector (myints, myints+8);            // 10 20 30 30 20 10 10 20
std::remove(myvector.begin(), myvector.end(), 20); // 10 30 30 10 10 ? ? ?

Note that remove does not actually delete the element, it just puts the element that needs to be removed to the end, and returns a new tail iterator,
For example, in the above example, the value in vector is generally //10, 30, 30, 10, 10, 10, 20 after the remove call
If you want to actually delete an element, you need to add the member function erase() to remove it.


myvector.erase(std::remove(myvector.begin(), myvector.end(), 20),myvector.end()); // 10 30 30 10 10

Unique ()

Similarly, the algorithm does not actually delete the element, but moves the element to the end of the interval.
Use the unique-erase usage:


int myints[] = {10,20,20,20,30,30,20,20,10};           // 10 20 20 20 30 30 20 20 10
std::vector<int> myvector (myints,myints+9);
std::vector<int>::iterator it;
it = std::unique (myvector.begin(), myvector.end());   // 10 20 30 20 10 ?  ?  ?  ?
myvector.erase(it,myvector.end());

The above is all the content of this article, I hope you can enjoy it.


Related articles: