排序似乎不起作用

时间:2015-04-14 13:31:46

标签: c++ algorithm sorting

此代码以C++编写。我有以下结构:

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

struct Data
{
    int h, b, w;

    Data(int _h, int _b, int _w) : h(_h), b(_b), w(_w)
    {}

    bool operator<(const Data& other) const
    {
        bool overlap = (other.b >= b && other.b <= w) ||
            (other.w >= b && other.w <= w) ||
            (other.b < b && other.w > w);
        if (overlap)
        {
            return h < other.h;
        }

        return h > other.h;
    }
};

operator<将用于排序。除非在比较变量中bw之间存在任何重叠,否则我们的想法是从最高h到最低h进行排序。剩下的代码:

vector <int> getOrdering(vector <int> height, vector <int> bloom, vector <int> wilt)
{
    vector<Data> vdata;

    for (int i = 0; i < height.size(); i++)
    {
        vdata.push_back(Data(height[i], bloom[i], wilt[i]));
    }

    sort(vdata.begin(), vdata.end());
    vector<int> ans;
    for (Data data : vdata)
    {
        ans.push_back(data.h);
    }

    return ans;
}

int main()
{
    vector <int> p0 = { 1, 2, 3, 4, 5, 6 };
    vector <int> p1 = { 1, 3, 1, 3, 1, 3 };
    vector <int> p2 = { 2, 4, 2, 4, 2, 4 };

    vector<int> ans = getOrdering(p0, p1, p2);

    for (int a : ans)
    {
        cout << a << ' ';
    }
    cout << endl;

    return 0;
}

我编写operator<函数的方式,代码应输出2 4 6 1 3 5。但输出为6 5 4 3 2 1。我使用的是Visual Studio 2013 Ultimate。

调试operator<函数后,我发现正在为Data对象调用它,如下所示:

1st call: this->h = 2, other.h = 1
2nd call: this->h = 1, other.h = 2
3rd call: this->h = 3, other.h = 2
4th call: this->h = 2, other.h = 3
5th call: this->h = 4, other.h = 3
6th call: this->h = 3, other.h = 4
7th call: this->h = 5, other.h = 4
8th call: this->h = 4, other.h = 5
9th call: this->h = 6, other.h = 5
10th call: this->h = 5, other.h = 6

请注意,Data对象&#39; h值为1,3或5,它们的b和w值相同。它们将按h的升序排序。对于h值为2,4和6的Data个对象也是如此。但在operator<()中,没有两个Data对象被比较,其h值相同! 1比2比2比3比3比4等。因此overlap变量始终为false。如果{h}值相同的sort()个对象被比较,那么Data的结果会有所不同 - 但这种情况从未发生过!

编译器的这种行为的任何解释?

1 个答案:

答案 0 :(得分:1)

这是因为您的运营商&lt;取决于很多数据顺序。如果我们使用您的数据运行您的算法,那么它就是预期的输出。

第一个比较数据是数据(1,1,2)和数据(2,3,4)。根据您的运算符&lt;,数据(2,3,4)是较低的,因此临时顺序是[数据(2,3,4),数据(1,1,2)]

然后,Data(3,1,2)出现并与当前排序列表的最低值进行比较,因此Data(2,3,4)。同样,根据您的运算符&lt;,数据(3,1,2)较低,因此无需与列表中的其他值进行比较,新的临时有序列表为[Data(3,1,2),Data(2) ,3,4),数据(1,1,2)]。

然后它对于每个其他值都是相同的,它们每次只与列表中的第一个值进行比较,因为它们较低(根据运算符&lt;)并且因此放在排序列表的前面。< / p>

如果您使用以下命令更改初始列表顺序:

vector <int> p0 = { 6, 5, 4, 3, 2, 1};
vector <int> p1 = { 3, 1, 3, 1, 3, 1};
vector <int> p2 = { 4, 2, 4, 2, 4, 2};

您将获得预期的输出,因为将涉及更多的比较。

但结果取决于初始化顺序的事实表明,您的运营商中存在明显的缺陷&lt;功能