繁体   English   中英

转换函数以与qsort一起使用

[英]convert function for use with qsort

我正在研究一个对向量进行操作的简单库。 它定义了一种经常使用的函数类型:

typedef float (*vec_pair_fun) (float x, float y);

出于易于使用的原因,我想创建一个排序函数,该函数使用vec_pair_fun比较向量的每个元素。 目前,我正在这样做:

static vec_pair_fun sort_function;

// follow improvements suggested by @chux below
static int converted_sort_function(const void* a, const void* b){
    //old code: return (int) qsort_function(*(float*)a,*(float*)b);
    float f = sort_function(*(float*)a,*(float*)b);
    return (f > 0.0f) - (f < 0.0f);
}

void vecx_sort(int x, float v[], vec_pair_fun func){
    sort_function=func;
    qsort(v,x,sizeof(float),converted_sort_function);
}

但是我真的不喜欢这种解决方法,因为它不是线程安全的,因为sort_function可以由另一个线程更改。

关于如何改善这一点的任何想法?


编辑:一种方法是自己对数组进行排序。 编码qsort确实不是我计划要做的,所以我很愿意提出建议

问:关于如何改善这一点的想法?
答:请勿将float结果intint进行比较。

可能不是OP的主要关注点,而是(int) sort_function(*(float*)a,*(float*)b); 弱。
FP点的结果可能是-0.40.4 ,它们都转换为(int) 0
FP点结果可能是> INT_MAX并且转换为int是UB。
建议:

static int converted_sort_function(const void* a, const void* b){
    float f = sort_function(*(float*)a,*(float*)b);
    return (f > 0.0f) - (f < 0.0f);
}

至于您的线程安全问题,请考虑qsort_s()上下文指针的qsort_s() qsort_s()是在C11附件K中指定的,因此它在编译器中可能不存在。

errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
    int (*compar)(const void *x, const void *y, void *context), 
    void *context);

Wikibooks的5th C实现Apple的 quicksort算法实现之后,我得以创建函数。 它似乎比stdlib版本快,并且没有全局/静态变量。

// x: length of v
// v: array of float
// func: a function that takes two float as argument and return a float
void vecx_qsort(unsigned int x, float v[], vec_pair_fun cmpf)
{
    float pivot,tmp;
    unsigned int al,l,r,ar,cnt;

    while (x>8)
    {
        cnt=0;

        al=l=1; r=ar=x-1;

        pivot=v[x/2];
        v[x/2]=v[0];
        v[0]=pivot;

        while (1)
        {
            while ( l<=r && (tmp=cmpf(v[l],pivot))<=0.0f ) {
                if(tmp==0.0f){
                    cnt=1;
                    vecx_swap(1,v+al,v+l); //swap vl & val
                    al++;
                }
                l++;
            }
            while ( l<=r && (tmp=cmpf(v[r],pivot))>=0.0f ) {
                if(tmp==0.0f){
                    cnt=1;
                    vecx_swap(1,v+r,v+ar);//swap vr & var
                    ar--;
                }
                r--;
            }

            if(l>r)
                break;
            cnt=1;
            vecx_swap(1,v+r,v+l);

            l++; r--;
        }

        if(cnt==0 && x<=32) // no swap made => almost sorted small array => insertion sort
            break;

        // swap values equal to pivot to the center
        cnt = (al<(l-al))?al:l-al;
        vecx_swap(cnt,v,v+l-cnt); // swap of element before al

        cnt = ((ar-r)<(x-ar-1))?ar-r:x-ar-1;
        vecx_swap(cnt,v+l,v+x-cnt); // swap of element after ar

        l=l-al;  // size of "smaller element array"
        r=ar-r;  // size of "bigger element array"

        // Recursion on the shorter side & loop (with new indexes) on the longer
        if (l>r) {
            vecx_qsort(r, v+x-r, cmpf);
            x=l;
        }
        else {
            vecx_qsort(l, v, cmpf);
            v+=x-r;
            x=r;
        }
    }

    // insertion sort
    for (r=1; r<x; r++)
    {
        pivot=v[r];
        for(l=r; l>0 && cmpf(pivot,v[l-1])<0.0f; l--)
            v[l]=v[l-1];
        v[l]=pivot;
    }
}

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM