qsort比较编译错误

时间:2014-10-23 00:22:07

标签: c++

我的medianfilter.cpp类调用qsort,如下所示。

vector<float> medianfilter::computeMedian(vector<float> v) {
    float arr[100];
    std::copy(v.begin(), v.end(), arr);

    unsigned int i;
    qsort(arr, v.size(), sizeof(float), compare);
    for (i = 0; i < v.size(); i++) {
        printf("%f ", arr[i]);
    }
    printf("median=%d ", arr[v.size() / 2]);
    return v;
}

我比较的实现是:

int medianfilter::compare(const void * a, const void * b) {
    float fa = *(const float*) a;
    float fb = *(const float*) b;
    return (fa > fb) - (fa < fb);
}

虽然mediafilter.hpp中的声明设置为私有,看起来像这样:

int compare (const void*, const void*);

发生编译错误:cannot convert ‘mediafilter::compare’ from type ‘int (mediafilter::)(const void*, const void*)’ to type ‘__compar_fn_t {aka int (*)(const void*, const void*)}’

我完全不理解这个错误。如何正确声明和实现此比较方法? 谢谢!

4 个答案:

答案 0 :(得分:5)

Compare是非静态成员函数,而qsort需要非成员函数(或静态成员函数)。由于您的比较函数似乎不使用该类的任何非静态成员,您可以将其声明为静态。事实上,我不确定你的中值滤波器类是什么。也许你只需要一个命名空间。

为什么不直接对矢量进行排序而不是将其复制到第二个数组中?此外,如果向量具有超过100个元素,则代码将中断。

sort的默认行为只是需要你,但为了完整起见,我展示了如何使用比较函数。

我还更改了函数的返回类型,因为我不明白为什么名为computeMedian的函数不会返回中位数。

namespace medianfilter
{
    bool compare(float fa, float fb)
    {
        return fa < fb;
    }

    float computeMedian(vector<float> v)
    {
        std::sort(v.begin(), v.end(), compare);
        // or simply: std::sort(v.begin(), v.end());
        for (size_t i = 0; i < v.size(); i++) {
            printf("%f ", v[i]);
        }

        if (v.empty())
        {
            // what do you want to happen here?
        }
        else
        {
            float median = v[v.size() / 2]; // what should happen if size is odd?
            printf("median=%f ", median); // it was %d before
            return median;
        }
    }
}

答案 1 :(得分:4)

你不能调用compare,因为它是一个成员函数,需要一个this指针(即需要在一个对象上调用它)。但是,由于比较函数不需要this指针,只需将其设为static函数即可编译。

在你的班级中声明它:

static int compare(const void * a, const void * b);

答案 2 :(得分:2)

与您的问题(您已经得到答案)没有直接关系,但有些意见:

  1. 您的中位数计算错误。如果元素数量是偶数,则应返回两个中心值的平均值,而不是低值的值。
  2. 具有设置大小的数组副本会尖叫缓冲区溢出。复制到另一个向量和std:对它进行排序或(正如@NeilKirk所建议的那样)只对原始数据进行排序,除非您有理由不对其进行修改。
  3. 没有防止空输入。在这种情况下,中位数是未定义的,但您的实现只会返回arr [0]
  4. 上发生的任何内容

答案 3 :(得分:2)

好的,这更像是Eli Algranti(优秀)答案的附录,而不是对原始问题的答案......请不要忘记忘记;)

这是一个通用代码,用于计算被称为quant的双向量的分位数x(下面的代码保留)。

首先要做的事情是:分位数有很多定义(R单独列表9)。下面的代码对应于定义#5(它也是matlab中的默认分位数函数,通常是统计学家在考虑分位数时所考虑的)。

这里的关键思想是,当分位数不落在精确观察上时(例如,当你想要长度为10的数组的15%分位数时),下面的实现实现了(正确的)插值(在这种情况下是相邻分位数之间的10%和20%)。这很重要,因此当你增加观察数量时(这里暗示名称medianfilter),分位数的值不会突然跳跃而是平滑收敛(这就是为什么这是统计学家的原因&# 39;首选定义)。

代码假定x至少有一个元素(下面的代码是较长的代码的一部分,我觉得这一点已经完成了。)

不幸的是它是使用(优秀!)c ++特征库中的许多函数编写的,对于我来说,在晚上的这个高级时间翻译特征函数 - 或者清理变量名称 - 为时已晚,但是关键想法应该是可读的。

#include <Eigen/Dense>
#include <Eigen/QR>

using namespace std;
using namespace Eigen;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using Eigen::VectorXi;

double quantiles(const Ref<const VectorXd>& x,const double quant){
//computes the quantile 'quant' of x.
    const int n=x.size();
    double lq,uq,fq;
    const double q1=n*(double)quant+0.5;
    const int index1=floor(q1);
    const int index2=ceil(q1);
    const double index3=(double)index2-q1;
    VectorXd x1=x;
    std::nth_element(x1.data(),x1.data()+index1-1,x1.data()+x1.size());
    lq=x1(index1-1);
    if(index1==index2){
        fq=lq;
    } else {
        uq=x1.segment(index1,x1.size()-index1-1).minCoeff();
        fq=lq*index3+uq*(1.0-index3);
    }
    return(fq);
}

所以代码使用一次调用nth_element,它具有平均复杂度O(n) [抱歉用于平均使用大O]和(当n是偶数时)一次额外调用min()[在本征方言中在向量的最多n / 2个元素上注明.minCoeff()],即O(n / 2)。

这比使用部分排序(这将花费O(nlog(n / 2)),worst case)或排序(这会花费)要好得多 O(nlogn)