0

我使用 AVL 构建了一个二叉树,然后将数据打包在一个数组中

typedef struct {
    void **data;
    int count;
} t_table;

比较函数如下所示:

int cmp(const void *pa, const void *pb)
{
    int a = *(int *)pa;
    int b = *(int *)pb;

    if (a > b)
        return +1;
    else
    if (b > a)
        return -1;
    else
        return 0;
}

我在 avl-tree 中插入并使用K&R qsort对指针数组进行排序没有问题。

现在我想使用的sandard函数qsort<stdlib.h>但我不得不使用一个新函数t_table(由于需要指针转换qsort),它看起来像:

int cmp(const void *pa, const void *pb)
{
    int a = *(int*)(*(void**)pa);
    int b = *(int*)(*(void**)pb);

    if (a > b)
        return +1;
    else
    if (b > a)
        return -1;
    else
        return 0;
}

我理解为什么必须更改函数(引用 C-FAQ):

要理解为什么在 qsort 比较函数中需要进行奇怪的指针转换(以及为什么在调用 qsort 时强制转换函数指针无济于事),思考 qsort 的工作原理是很有用的。qsort 对被排序的数据的类型或表示一无所知:它只是在小块内存中随机播放。(它只知道块的大小,您在 qsort 的第三个参数中指定。)为了确定两个块是否需要交换,qsort 调用您的比较函数。(为了交换它们,它使用 memcpy 的等价物。)

但我想知道是否有任何替代方法(使用stdlib qsort)来避免必须维护两个比较函数(一个用于 avl,另一个用于void **

4

2 回答 2

2

我不确定您是否真的可以避免维护这两个功能,但是您可以执行以下操作:

int cmp_int(const void *pa, const void *pb)
{
    int a = *(int *)pa;
    int b = *(int *)pb;

    return cmp(a, b);
}

int cmp_voidp(const void *pa, const void *pb)
{
   int a = *(int*)(*(void**)pa);
   int b = *(int*)(*(void**)pb);

   return cmp(a, b);
}

static int cmp(const int a, const int b)
{
    if (a > b)
        return +1;
    else
    if (b > a)
        return -1;
    else
        return 0;
}

你有3个功能,但你不重复自己,更容易维护。

编辑:就像Sergey L.说的,如果你使用C99,cmp可能是一个static inline函数。

于 2013-08-09T12:26:12.813 回答
1

您不能使用完全相同的功能,但您可以根据第一个定义第二个:

int cmp2(const void *pa, const void *pb)
{
    return cmp(*(void **)pa, *(void **)pb);
}
于 2013-08-09T12:25:22.400 回答