Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Iterator and reverse iterator

what is difference between the following two code snippets.

vector<int> a;
// initialization code
sort( a.rbegin(), a.rend() );

and

vector<int> a;
// same initialization as above
sort(a.begin(), a.end(), comp);

where comp is a boolean function given below

bool comp( int i, int j)
{
    return i>j;
}

To illustrate, the following code gives WA while this code gives AC for SPOJ problem XMAX. The only difference between AC and WA is the version of sort() used.

like image 928
spv Avatar asked Dec 15 '22 15:12

spv


2 Answers

The two function calls do NOT give the same answer because std::sort is not a stable algorithm, i.e. it does not keep identical elements in their relative ordenings. Below an example where elements of std::pair<int, int> are sorted on their first element. Sorting and sorting in reverse order with the reversed comparison function does not yield identical sequences. Doing the same with std::stable_sort does yield identical results.

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

int main()
{
    typedef std::pair<int, int> Element;
    std::vector<Element> v;

    v.push_back( Element(1,1) );
    v.push_back( Element(-1,1) );
    v.push_back( Element(1,2) );
    v.push_back( Element(-1,2) );
    v.push_back( Element(1,3) );
    v.push_back( Element(-1,3) );
    v.push_back( Element(1,4) );
    v.push_back( Element(-1,4) );
    v.push_back( Element(1,5) );
    v.push_back( Element(-1,5) );
    v.push_back( Element(1,6) );
    v.push_back( Element(-1,6) );
    v.push_back( Element(1,16) );
    v.push_back( Element(-1,16) );
    v.push_back( Element(1,22) );
    v.push_back( Element(-1,22) );
    v.push_back( Element(1,33) );
    v.push_back( Element(-1,33) );
    v.push_back( Element(1,44) );
    v.push_back( Element(-1,44) );
    v.push_back( Element(1,55) );
    v.push_back( Element(-1,55) );
    v.push_back( Element(1,66) );
    v.push_back( Element(-1,66) );

    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << "(" << it->first << "," << it->second << ")" << " ";
    }
    std::cout << "\n";

    auto w1 = v;
    std::sort(w1.begin(), w1.end(), [](Element const& e1, Element const& e2){ 
       return e1.first < e2. first;
    });
    auto w2 = v;
    std::sort(w2.rbegin(), w2.rend(), [](Element const& e1, Element const& e2) {
       return e1.first > e2.first;
    });
    std::cout << std::boolalpha << std::equal(w1.begin(), w1.end(), w2.begin()) << "\n";

    auto w3 = v;
    std::stable_sort(w3.begin(), w3.end(), [](Element const& e1, Element const& e2){ 
       return e1.first < e2. first;
    });
    auto w4 = v;
    std::stable_sort(w4.rbegin(), w4.rend(), [](Element const& e1, Element const& e2) {
       return e1.first > e2.first;
    });
    std::cout << std::boolalpha << std::equal(w3.begin(), w3.end(), w4.begin()) << "\n";

}

Output on LiveWorkSpace

like image 109
TemplateRex Avatar answered Dec 28 '22 23:12

TemplateRex


Reverse iterators simple iterate in the reverse direction of normal iterators.

So, both snippets will sort everything inside the range [first, last] both in ascending order. The difference is in the first it will use the < operator for comparison and in the second your given function.

In detail the first actually is sorting in non-ascending order but since you also reverse tho comparison it gets reversed again, which neutralizes the effect.

NOTE: Elements that would compare equal to each other are not guaranteed to keep their original relative order.

USEFUL REFERENCES: std::sort, std::vector::begin, std::vector::end, std::vector::rbegin, std::vector::rend

like image 45
0xJarno Avatar answered Dec 29 '22 00:12

0xJarno