简体   繁体   中英

Sorting vectors in c++

I need to sort the data structure vector<pair<unsigned, pair<vector<unsigned>, vector<unsigned> > > > sbp first by sbp.second.second vector and for equal values of sbp.second.second by sbp.second.first -- both the vectors are compared by (i) size of vectors; (ii) if size of vectors are equal, then vectors are lexicographically sorted. For doing so, I wrote the following code. But I dont know why but this code is getting stuck in an infinite loop. Can someone please help me with as to where am I going wrong.

#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef std::pair<std::vector<unsigned>, std::vector<unsigned> > vec_pair;

bool sortingFunc(const pair<unsigned,vec_pair>& a, const pair<unsigned,vec_pair>& b)
{
    if((a.second).second.size() == (b.second).second.size()) {
        if(std::lexicographical_compare((a.second).second.begin(), (a.second).second.end(), (b.second).second.begin(), (b.second).second.end()))//a<b
        {
            return true;
        }else{
            if((a.second).first.size() == (b.second).first.size()) {
                return std::lexicographical_compare((a.second).first.begin(), (a.second).first.end(), (b.second).first.begin(), (b.second).first.end());
            } else {
                // Sort by size.
                return (a.second).first.size() < (b.second).first.size();
            }            
        }
    } else {
        // Sort by size.
        return (a.second).second.size() < (b.second).second.size();
    }
}

int main()
{
    vector<pair<unsigned, pair<vector<unsigned>, vector<unsigned> > > > sbp;
    std::sort(sbp.begin(), sbp.end(), sortingFunc);
}

I am using C++11 (gcc 4.8.2)

I would use std::tie or make_tuple with rvalue:

bool sortingFunc(const pair<unsigned, vec_pair>& a, const pair<unsigned, vec_pair>& b)
{
    return std::make_tuple(a.second.second.size(), std::ref(a.second.second), a.second.first.size(), std::ref(a.second.first))
         < std::make_tuple(b.second.second.size(), std::ref(b.second.second), b.second.first.size(), std::ref(b.second.first));
}

Your case is not correct with

if(std::lexicographical_compare((a.second).second.begin(), (a.second).second.end(), (b.second).second.begin(), (b.second).second.end()))//a<b
{
    return true;
}

where it misses b < a condition.

else if(std::lexicographical_compare((b.second).second.begin(), (b.second).second.end(), (a.second).second.begin(), (a.second).second.end()))//b < a
{
    return true;
}

before the == condition.

The problem with your code is that for this condition:

if(std::lexicographical_compare((a.second).second.begin(), (a.second).second.end(), (b.second).second.begin(), (b.second).second.end()))//a<b

You do not correctly handle the opposite condition. That is, the above line only tests if (a.second.second < b.second.second) . If it's true, you return true from the function, which is correct. But if it's false, you then go on to check the lower priority conditions, ignoring the possible case that b.second.second could be less than a.second.second .

Also, a slight modification of Jarod42's std::tie method:

bool sortingFunc(const pair<unsigned, vec_pair>& a, const pair<unsigned, vec_pair>& b)
{
    auto  a1 = a.second.second.size();
    auto& a2 = a.second.second;
    auto  a3 = a.second.first.size();
    auto& a4 = a.second.first;

    auto  b1 = b.second.second.size();
    auto& b2 = b.second.second;
    auto  b3 = b.second.first.size();
    auto& b4 = b.second.first;

    return std::tie(a1, a2, a3, a4) < std::tie(b1, b2, b3, b4);
}

What std::tie does is make a std::tuple of references to its arguments. And operator< is overloaded for std::tuple to do a lexicographical comparison on its elements from the first to the last.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM