Learning note algorithm of C++STL standard library

Posted by savingc on Wed, 02 Feb 2022 03:15:23 +0100

preface:

In this note, I annotated most of the code. Some of my ideas and comments were marked in blue, and the key points and areas needing attention were marked in red.

In this article, we mainly introduce the algorithms in STL.

Text:

1. STL algorithm classification

Algorithms in STL can be roughly divided into the following seven categories:

Invariant sequence algorithm

Variable value algorithm

Deletion algorithm

Variable order algorithm

Sorting algorithm

Ordered interval algorithm

Numerical algorithm

2. STL algorithm

Most overload algorithms have two versions

Use "= =" to judge whether the elements are equal, or use "<" to compare the size

One more type parameter "pred" and function parameter "pred op":

By judging the return value of the expression "op(x,y)": true/false

To determine whether x is "equal to" Y, or whether x is "less than" y

If there are two versions of min_element:
  iterator min_element(iterator first, iterator last);

  iterator min_element(iterator first, iterator last, Pred op);

(in fact, there is one more comparison rule to be passed in)

2.1. Invariant sequence algorithm

This kind of algorithm will not modify the container or object used by the algorithm

Applies to sequential and associative containers

Time complexity is O(n)

min: find the smaller of the two objects (the comparator can be customized)

max: find the larger of the two objects (you can customize the comparator)

  min_element: find the minimum value in the interval (the comparator can be customized)

  max_element: find the maximum value in the interval (the comparator can be customized)

  for_each: do some operation on each element in the interval

count: the number of elements equal to a certain value in the calculation interval

  count_if: calculate the number of elements that meet certain conditions in the interval

Find: find the element equal to a certain value in the interval

  find_if: find elements that meet certain conditions in the interval

  find_end: find the position of the last occurrence of another interval in the interval (the comparator can be customized)

  find_first_of: find the first element appearing in another interval in the interval (the comparator can be customized)

  adjacent_find: find the position where two consecutive equal elements appear for the first time in the interval (the comparator can be customized)

search: find the position of the first occurrence of another interval in the interval (the comparator can be customized)

  search_n: Find n consecutive elements equal to a certain value for the first time in the interval (the comparator can be customized)

Equal: judge whether the two intervals are equal (the comparator can be customized)

mismatch: compare the elements of two intervals one by one, and return the position of the two elements that are unequal for the first time (the comparator can be customized)

  lexicographical_compare: compare the size of two intervals in dictionary order (the comparator can be customized)

  find:

  template<class init, class T>

  init find(init first, init last, const T& val);

Return iterator i in [first, last], so that * i==val

  find_if:

  templast<class init, class Pred>

  init find_if(init first, init last, pred pr);

Returns the iterator i in the interval [first, last], so that pr(*i)==true

(so the pr passed in is a function? Check it out. It is a unary predicate, that is, a function object with only one parameter and the return value is limited to bool)

  for_each:

  template<class init, class Fun>

  Fun for_each(init first, init last, Fun f);

For each element e in [first, last], execute f(e), requiring that f(e) cannot change e

  count:

  template<class init, class T>

  size_t count(init first, init last, const T& val);

Calculate the number of elements equal to val in [first, last] (x==y is true)

  count_if:

  template<class init, class Pred>

  size_t count_if(init first, init last, Pred pr);

Calculate the number of elements e conforming to pr(e)==true in [first, last]

(the usage feels similar to find_if)

  min_element:

  template<class Fwdlt>

  Fwdlt min_element(Fwdlt first, Fwdlt last);

Returns the iterator of the smallest element in [first, last], with "<" as the comparator

The smallest means that no element is smaller than it, not that it is smaller than other different elements

Because even a= b. A < B and B < A may not be true

  max_element:

  template<class Fwdlt>

  Fwdlt max_element(Fwdlt first, Fwdlt last);

Returns the iterator of the largest element (not less than any other element) in [first, last]

It also uses "<" as the comparator

Example:

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 class A
 5 {
 6 public:
 7     int n;
 8     A(int i):n(i){}
 9 };
10 bool operator<(const A & a1, const A & a2)
11 {
12     cout<<"< called"<<endl;
13     if (a1.n==3&&a2.n==7)
14     {
15         return true;
16     }
17     return false;
18 }
19 int main(int argc, char const *argv[])
20 {
21     A aa[] = {3,5,7,2,1};
22     cout<<min_element(aa,aa+5)->n<<endl;
23     cout<<max_element(aa,aa+5)->n<<endl;
24     return 0;
25 }
26 /*
27 Output:
28 < called
29 < called
30 < called
31 < called
32 3
33 < called
34 < called
35 < called
36 < called
37 7
38 */

(here, suppose the first element is the minimum value, and then compare it one by one. It is found that the first element is really the minimum value under the defined "<", and the result is 3. In the second case, it is found that 3 < 7, and the result is 7)

2.2. Variable value algorithm

Such algorithms modify the values of the elements of the source interval or the target interval

The interval in which the value is modified cannot belong to the associated container (because if it is modified, the order of the associated container will be broken)

  for_each: do some operation on each element in the interval (different from the previous one is whether the passed function parameter is const)

Copy: copy an interval elsewhere

  copy_backward: copy an interval to another place, but the target interval is modified from back to front

transform: copy elements from one interval to another after deformation

  swap_ranges: exchange the contents of two intervals

Fill: fill the interval with a value

  fill_n: Replace n elements in the interval with a value

Fill the result of an operation with generate

  generate_n: Replace n elements in the interval with the result of an operation

Replace: replace a value in the interval with another value

  replace_if: replace the value that meets certain conditions in the interval with another value

  replace_copy: copy an interval to another interval. When copying, a value should be copied with a new value

  replace_copy_if: copy an interval to another interval. When copying, the value that meets certain conditions shall be replaced with a new value and copied

transform:

  template<class init, class Outit, class Unop>

  Outit transform(init first, init last, outit x, Unop uop);

For each iterator l in [first, last),

Execute uop(*i); And put the results in the place starting from x

It is required that uop(*i) shall not change the value of * i

The return value of this template is an iterator, i.e. x + (last first)

x can be equal to first

Example: (including some things that have not been mentioned before and)

 1 #include<vector>
 2 #include<iostream>
 3 #include<numeric>
 4 #include<list>
 5 #include<algorithm>
 6 #include<iterator>
 7 using namespace std;
 8 class CLessThen9
 9 {
10 public:
11     bool operator()(int n){return n < 9;}
12 };
13 void outputSquare(int value){cout<<value*value<<" ";}
14 int calculateCube(int value){return value*value*value;}
15 
16 int main(int argc, char const *argv[])
17 {
18     const int SIZE = 10;
19     int a1[] = {1,2,3,4,5,6,7,8,9,10};
20     int a2[] = {100,2,8,1,50,3,8,9,10,2};
21     vector<int> v(a1,a1+SIZE);
22     ostream_iterator<int> output(cout," ");
23     random_shuffle(v.begin(),v.end());//Randomly disrupt the value of the interval
24     cout<<endl<<"1)";//Output: 1)9 2 10 3 1 6 8 4 5 7((random here)
25     copy(v.begin(),v.end(),output);
26     copy(a2,a2+SIZE,v.begin());
27     cout<<endl<<"2)";//Output: 2)2
28     cout<<count(v.begin(),v.end(),8);
29     cout<<endl<<"3)";//Output: 3)6
30     cout<<count_if(v.begin(),v.end(),CLessThen9());//The object is called here
31     cout<<endl<<"4)";//Output: 4)1
32     cout<<*(min_element(v.begin(),v.end()));
33     cout<<endl<<"5)";//Output: 5)100
34     cout<<*(max_element(v.begin(),v.end()));
35     cout<<endl<<"6)";//Output: 6)193
36     cout<<accumulate(v.begin(),v.end(),0);//Sum and add up to 0
37     cout<<endl<<"7)";//Output: 10000 4 64 1 2500 9 64 81 100 4
38     for_each(v.begin(),v.end(),outputSquare);
39     vector<int> cubes(SIZE);
40     transform(a1,a1+SIZE,cubes.begin(),calculateCube);//a1 Where's the cube cubes inside
41     cout<<endl<<"8)";//Output: 1 8 27 64 125 216 343 512 729 1000
42     copy(cubes.begin(),cubes.end(),output);
43     
44     return 0;
45 }

Of which:

  ostream_iterator<int> output(cout," ");

An ostream is defined_ Iterator < int > object, which can output integers divided by "" (space) through cout

  copy(v.begin(),v.end(),output);

The content that causes v is output on cout

(the teacher played impassioned music when he talked here)

  copy:

  template<class init, class outit>

  outit copy(init first, init last, outit x);

This function executes * (x+N) = *(first+N) for each N in the interval [0, last first), and returns x+N

For copy(v.begin(),v.end(),output);

The types of first and last are vector < int >:: const_ iterator

The type of output is ostream_ iterator<int>

copy source code

1 template<class _ll, class _ol>
2 inline _ol copy(_ll _F,_ll _L,_ol _X)
3 {
4     for (;_F != _L; ++_X,++_F)
5         *_X = *_F;
6     return(_X);
7 }

A question, how to write my in the following program_ ostream_ iterator?

 1 #include<iostream>
 2 #include<fstream>
 3 #include<string>
 4 #include<algorithm>
 5 #include<iterator>
 6 using namespace std;
 7 int main(int argc, char const *argv[])
 8 {
 9     int a[4] = {1,2,3,4};
10     My_ostream_iterator<int> oit(cout,"*");
11     copy(a,a+4,oit);//Output 1*2*3*4*
12     ofstream oFile("test.txt",ios::out);
13     My_ostream_iterator<int> oitf(oFile,"*");
14     copy(a,a+4,oitf);//towards text.txt Write 1 to file*2*3*4
15     oFile.close();
16     return 0;
17 }//How to write My_ostream_iterator???

After instantiating the "copy(a,a+4,oit)" in the above program, we get copy as follows:

1 template<class _ll, class _ol>
2 inline My_ostream_iterator<int> copy(int _F,int _L,My_ostream_iterator<int> _X)
3 {
4     for (;_F != _L; ++_X,++_F)
5         *_X = *_F;
6     return(_X);
7 }

  My_ ostream_ The iterator class should overload the "+ +" and "*" operators

"=" should also be overloaded

 1 #include<iterator>
 2 #include<iostream>
 3 #include<string>
 4 template<class T>
 5 class My_ostream_iterator:public iterator<output_iterator_tag, T>
 6 {
 7     private:
 8     string sep;//Separator
 9     ostream & os;
10     public:
11     My_ostream_iterator(ostream & o,string s):sep(s),os(o){}
12     void operator++(){};//++You only need to have a definition, and you don't need to do anything
13     My_ostream_iterator & operator*(){return *this;}
14     My_ostream_iterator & operator=(const T & val)
15     { os<<val<<sep;return *this;}
16 };

(io Liu stunned me 555)

Postscript:

This class is so long. Next time I see such a long class, I will.... After reading it, I can't help learning, right? Don't say it. Happy new year, everyone. I wish you good luck!