如何根据第二个元素对std :: set进行排序?

时间:2019-07-15 11:51:49

标签: c++ sorting stdset custom-compare

在二维空间中给出chkdsk个点,并按的顺序对所有点进行排序。

n

输入规范

第一行由整数(x1,y1) > (x2,y2) if and only if (x1>x2) or (x1==x2 && y1<y2) 组成,即测试用例的数量。然后,对于每个测试用例,第一行由整数t(点数)组成。然后接下来的n行包含两个整数nxi代表该点。

输出规范

对于每个测试用例,打印点的排序顺序。 输入限制:

yi

注意:严格的时间限制。首选1 <= t <= 10 1 <= n <= 100000 - 10 ^ 9 <= co - ordinates <= 10 ^ 9 / scanf / printf而不是BufferedReader / cin / cout

样本输入

Scanner

示例输出

1
5
3 4
-1 2
5 -3
3 3
-1 -2

我声明了-1 2 -1 -2 3 4 3 3 5 -3 ,现在我想对如果键相等,则按降序排序(值)。这是我的代码:

set

我的输出

int main() 
{
    int n, i, hold = 0;
    set<pair<int, int>>s;
    int x, y, t;
    set<pair<int, int>>::iterator it;

    SF(t)
        while (t--)
        {

            SF(n) while (n--) {
                SF(x) SF(y)
                    s.insert({ x,y });
            }

            for (it = s.begin(); it != s.end(); it++) {
                PF(it->first) printf(" "); PF(it->second); printf("\n");
            }
            s.clear();
        }
    return 0;
}

如果键相同,我希望键值降序排列。

3 个答案:

答案 0 :(得分:1)

默认情况下,Set不会按照您想要的方式排序,因此您必须提供自己的比较功能。

struct MyComp
{
    bool operator()(const pair<int,int>& x, const pair<int,int>& y) const
    {
        return x.first < y.first || (x.first == y.first && x.second > y.second);
    }
};

set<pair<int,int>, MyComp> s;

答案 1 :(得分:1)

std::set默认使用std::less作为默认比较器,以比较插入到其中的元素。

在您的情况下,您将std::pair<int,int>作为元素类型,因此std::set使用标准中定义的std::pair的{​​{3}},因此您没有您想要的结果。

为了实现自定义样式比较,您需要提供一个自定义比较器

template<
    class Key,
    class Compare = std::less<Key>,
 //                 ^^^^^^^^^^^^^^^ --> instead of this
    class Allocator = std::allocator<Key>
> class set;

应符合default operator<的要求。 从C ++ 11开始,您还可以为此使用lambda函数:

以下是示例代码示例:compare

#include <iostream>
#include <set>
using  pairs = std::pair<int, int>;

int main()
{
    // custom compare
    const auto compare = [](const pairs &lhs, const pairs &rhs) 
    {
        return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second > rhs.second);
    };

    std::set<pairs, decltype(compare)> mySet(compare);

    mySet.emplace(3, 4);
    mySet.emplace(-1, 2);
    mySet.emplace(5, -3);
    mySet.emplace(3, 3);
    mySet.emplace(-1, -2);

    for (const auto& it : mySet)
        std::cout << it.first << " " << it.second << std::endl;
}

输出

-1 2
-1 -2
3 4
3 3
5 -3

答案 2 :(得分:0)

根据Jejo和其他人的回答,您可以创建一个自定义比较器来指定要如何对点进行排序:

// custom compare
const auto compare = [](const pairs &lhs, const pairs &rhs) 
{
    return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second > rhs.second);
};

set<pair<int, int>, decltype(compare)> mySet(compare);

但是,如果您关心性能,则可能会发现使用std :: vector并调用std :: sort比std :: set / insert替代要快得多:

#include <vector>
#include <algorithm>
using namespace std;

int main() 
{
    int n, i, hold = 0;
    vector<pair<int, int>> v;
    int x, y, t;

    SF(t)
        while (t--)
        {

            SF(n) 
            v.reserve(n);
            while (n--) {
                SF(x) SF(y)
                    v.emplace_back( x,y );
            }

            // custom comparitor
            const auto comp = [](const pairs &lhs, const pairs &rhs) 
            {
                return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second > rhs.second);
            };

            sort(v.begin(), v.end(), comp);

            for (const auto &p : v) {
                PF(p.first) printf(" "); PF(p.second); printf("\n");
            }
            v.clear();
        }
    return 0;
}

为什么插入集合要比插入向量然后进行排序慢一些原因:

  1. std :: set实现涉及二叉树,通常是红黑树。 See here for details.
  2. 遍历std :: set中的元素范围为much slower

请注意,这两种方法都需要n个分配,并且需要按nlog(n)个操作的顺序进行插入和排序。