在C ++中排序时输出错误

时间:2016-09-28 15:37:19

标签: c++ sorting qsort

以下C ++代码使用qsort按降序对数组进行排序:

#include<iostream>
#include<cstdio>
#include <stdlib.h>
using namespace std;

struct player {
  double data;
  int index;
};

struct player A[] = {{0.690277,0}, {0.517857,1}, {0.780762,2}, {0.0416667,3}, {0.0416667,4}};

int compare (const void * a, const void * b)
{
   return ( ((struct player*)b)->data - ((struct player*)a)->data );
}

int main ()
{
  int n;
  qsort (A, 5, sizeof(struct player), compare);
  for (n=0; n<5; n++)
  printf ("data=%lf, index=%d\n", A[n].data, A[n].index);
  return 0;
}

但我得到这样的输出:

data=0.517857, index=1
data=0.780762, index=2
data=0.041667, index=3
data=0.041667, index=4
data=0.690277, index=0

代码中有什么问题吗?

2 个答案:

答案 0 :(得分:8)

compare中,你减去两个sub-1双精度并将它们转换为int,结果在大多数情况下为0.而不是减去你应该比较它们并返回-1/1。

答案 1 :(得分:5)

请考虑使用此比较:

int compare (const void * a, const void * b)
{
    auto x = reinterpret_cast<const player*>(a);
    auto y = reinterpret_cast<const player*>(b);
    if(x->data < y->data)
        return -1;
    if(x->data > y->data)
        return 1;
    return 0;
}

也就是说,这种编码风格是古老/弃用/不良做法。

考虑写一下这类似的内容:

#include<iostream>
#include <algorithm>

struct player {
  double data;
  int index;

    bool operator < (const player& p) const
    {
        return data < p.data;
    }
};

auto A = std::vector<player>{
    {0.690277,0}, {0.517857,1},
    {0.780762,2}, {0.0416667,3}, {0.0416667,4}
};

int main ()
{
    std::sort(std::begin(A), std::end(A));
    for(const auto& x: A)
        std::cout << "data=" << x.data << ", "
            << "index=" << x.index << "\n";
}

建议的更改:

  • 不要全局导入标准名称
  • 不要混用cstdio和iostreams(只包括其中一个)
  • 使用std :: vector或std :: array而不是native array
  • 在类的接口(bool运算符&lt;)中定义排序顺序。 (这也应该意味着你定义了其他算术运算符 - 这是一种很好的做法,以后会避免细微的错误,但这个特定的实现不需要编译和工作)。
  • 使用std :: sort而不是qsort
  • 不要使用原始指针(使用它们就像这是bug的来源)