简体   繁体   English

如何对向量进行排序<pair<pair<float, float> , unsigned int>> 由第一个浮点数,如果有平局第二个浮点数? </pair<pair<float,>

[英]How can I sort a vector<pair<pair<float, float>, unsigned int>> by the first float, and if there's a tie the second float?

I have a priority queue with 'keys' that currently looks like this:我有一个带有“键”的优先级队列,目前看起来像这样:

using HeapKey = pair<Cost, Cost>;
vector<pair<HeapKey, unsigned int>> U;

I insert in the queue with this command:我用这个命令插入队列:

push_heap(U.begin(), U.end(), KeyCompare());

And I have a sorting command like this:我有一个这样的排序命令:

struct KeyCompare {
  bool operator()(const pair<HeapKey, unsigned int>& a, const pair<HeapKey, unsigned int>& b) const
  {
    return a.first > b.first;
  }
};

I haven't worked with heaps very much, and my inexperience shows.我没有太多地使用堆,而且我的经验不足。 I've read that heaps traditionally works by having the largest element first.我读过传统上堆的工作原理是首先拥有最大的元素。 I need the smallest.我需要最小的。 But I also need the queue to be sorted by lexicographical order so that a key is less than or equal to another key if:但我还需要按字典顺序对队列进行排序,以便在以下情况下,一个键小于或等于另一个键:

(k1.first <= k2.first) OR (k1.first == k2.first AND k1.second <= k2.second)

And I wonder how exactly I code that in C++?我想知道我是如何在 C++ 中编码的? Currently my code doesn't seem to work a 100% since mostly get the smallest element defined by the k1.first, but not always, and I need to implement that check of the second element if two keys are equal so I can sort my priority queue.目前,我的代码似乎无法 100% 正常工作,因为大多数情况下都是获取 k1.first 定义的最小元素,但并非总是如此,如果两个键相等,我需要对第二个元素进行检查,这样我就可以对我的代码进行排序优先队列。

Thank you谢谢

Edit:编辑:

Sorry about the lack of code.抱歉缺少代码。 Took me a little while but I think I have a good example with this:花了我一段时间,但我想我有一个很好的例子:

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

using Cost = float;
using HeapKey = pair<Cost, Cost>;
vector<pair<HeapKey, unsigned int>> U;

struct KeyCompare {
  bool operator()(const pair<HeapKey, unsigned int>& a, const pair<HeapKey, unsigned int>& b) const
  {
    return a.first > b.first;
  }
};

ostream& operator<<(ostream& os, pair<Cost, Cost> const& p) {
  return os << "<" << p.first << ", " << p.second << ">";
}
 
int main()
{
    U.push_back({ {5.62843, 2.8}, 1 });
    U.push_back({ {5.64264, 1.4}, 2 });
    U.push_back({ {6.01976, 1}, 3 });
    U.push_back({ {6.2, 5.2}, 4 });
    U.push_back({ {6.03607, 3.8}, 5 });
    U.push_back({ {6.03607, 3.8}, 6 });
    U.push_back({ {7.45028, 3.8}, 13 });
    U.push_back({ {7.45028, 3.8}, 14 });
    U.push_back({ {7.45028, 3.8}, 15 });
    U.push_back({ {5.62843, 1}, 16 });
    U.push_back({ {5.02843, 7.8}, 17 });
    push_heap(U.begin(), U.end(), KeyCompare());

    cout << "U: ";
    for (auto p : U) {
        cout << p.second << p.first << " - ";
    }
    cout << endl;

    for (int i = 0; i < 5; i++) {
        pop_heap(U.begin(), U.end(), KeyCompare());
        U.pop_back();
        cout << U.front().second << U.front().first << endl;
    }
}

So, what I get from this is:所以,我从中得到的是:

U: 17<5.02843, 7.8> - 1<5.62843, 2.8> - 3<6.01976, 1> - 4<6.2, 5.2> - 2<5.64264, 1.4> - 6<6.03607, 3.8> - 13<7.45028, 3.8> - 14<7.45028, 3.8> - 15<7.45028, 3.8> - 16<5.62843, 1> - 5<6.03607, 3.8> - 
1<5.62843, 2.8>
2<5.64264, 1.4>
16<5.62843, 1>
3<6.01976, 1>
6<6.03607, 3.8>

And the problem I believe I'm having is, as you can see, that after I pop elements 17 I have element 1 as the next.我认为我遇到的问题是,如您所见,在我弹出元素 17 之后,下一个元素是元素 1。 However, element 16's first key is of equal size and it's second key is smaller, so I would like that to go first.但是,元素 16 的第一个键大小相等,而第二个键较小,所以我想先输入 go。

Furthermore element 2 comes before element 16 and 16's first key is smaller than element 2's first key, so that's not right.此外,元素 2 在元素 16 之前出现,并且 16 的第一个键小于元素 2 的第一个键,所以这是不对的。

Hope this is better.希望这会更好。

  • You are using the wrong function ( std::push_heap ) to create a max heap.您使用错误的 function ( std::push_heap ) 来创建最大堆。 push_heap puts the last element in an already existing max heap in its correct place. push_heap将已存在的最大堆中的最后一个元素放在正确的位置。 Use std::make_heap to create the heap.使用std::make_heap创建堆。
     std::make_heap(U.begin(), U.end(), KeyCompare());
  • The comparator needs to compare the second float before the first and possibly also the unsigned int to get the job done properly.比较器需要先比较第二个float ,然后再比较第一个浮点数,可能还需要比较unsigned int才能正确完成工作。 To make that easy, use std::tie .为方便起见,请使用std::tie If you for example want the smallest values extracted first:例如,如果您想要首先提取最小值:
     #include <tuple> struct KeyCompare { bool operator()(const std::pair<HeapKey, unsigned int>& a, const std::pair<HeapKey, unsigned int>& b) const { return std::tie(a.first.second, a.first.first, a.second) > std::tie(b.first.second, b.first.first, b.second); } };
    The above is the same as you would get if you instead did it manually like below:如果您改为手动执行,则上面的内容与您将获得的结果相同,如下所示:
     struct KeyCompare { bool operator()(const std::pair<HeapKey, unsigned int>& a, const std::pair<HeapKey, unsigned int>& b) const { if(a.first.second > b.first.second) return true; if(a.first.second < b.first.second) return false; if(a.first.first > b.first.first) return true; if(a.first.first < b.first.first) return false; if(a.second > b.second) return true; return false; }
    To switch ascending/descending order, just flip the < / > operators.要切换升序/降序,只需翻转< / >运算符。 When you use std::tie , you can use members from both a and b to create each tuple.使用std::tie时,可以使用ab中的成员来创建每个元组。 In the example below I've put b.second in the first and a.second in the last.在下面的示例中,我将b.second放在第一个,将a.second放在最后。 The float s will then be ordered in ascending order while the unsigned int will be in descending order. float将按升序排列,而unsigned int将按降序排列。
     return std::tie(a.first.second, a.first.first, b.second) > std::tie(b.first.second, b.first.first, a.second);
  • You access the wrong element when you print out the result.当您打印出结果时,您访问了错误的元素。 The value to be popped from the heap is in U.back() after you've called std::pop_heap , not in U.front() .在调用std::pop_heap之后,要从堆中弹出的值在U.back()中,而不是在U.front()中。 You can simply reorganize your code to do it properly:您可以简单地重新组织代码以正确执行此操作:
     while(not U.empty()) { std::cout << U.front().second << ' ' << U.front().first << '\n'; std::pop_heap(U.begin(), U.end(), KeyCompare()); U.pop_back(); }

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 访问地图中的.first或.second时出错 <std::pair<float,float> ,std :: vector <float> &gt; - Getting error when accessing .first or .second in map <std::pair<float,float>, std::vector<float> > 带浮点数组的std :: make_pair(float2,unsigned int) - std::make_pair with float array (float2, unsigned int) C ++是否可以从对定义隐式转换 <int, int> 配对 <float,float> ? - C++ Is it possible to define a implicit conversion from pair<int, int> to pair<float,float>? 如何比较矢量<float>和浮动*</float> - How to compare vector<float> and float* 如何在 C++ 中将浮点数转换为无符号整数? - How to convert a float into an unsigned int in C++? 从unsigned int转换为float - Conversion from unsigned int to float 对 push_back 与对交互的混淆<float,int> - Confusion on push_back interaction with pair<float,int> 为什么是std :: pair <int, int> 可从const std :: pair构造 <int, float> &? - Why is std::pair<int, int> constructible from a const std::pair<int, float>&? 如何将float变量赋值给unsigned int变量,bit image,而不是cast - How can I assign a float variable to an unsigned int variable, bit image, not cast 将范围限制浮点数转换为无符号整数维持排序顺序和精度? - Convert range limited float to unsigned int maintaining sort order and precision?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM