Qsort()不适用于结构

时间:2017-10-20 14:36:03

标签: c algorithm pointers struct qsort

我目前正在图上实现一些算法,我使用一个结构来保存图中每个边的信息:它的源顶点,它的目标顶点和它的权重。

我的结构声明如下:

typedef struct edge {
   int data[3]; //src, dest, weight
} edge_t, *edge_p; 

然后我创建一个变量指针并为n结构分配内存,其中n是图中的多个边:

edge_p localEdges = (edge_p)malloc(n*sizeof(edge_t));

然后我用相同类型的另一个struct localEdges的值填充struct allEdges

for (int i = 0; i < num_edges; i++) {
    localEdges[i].data[0] = allEdges[i].data[0];
    localEdges[i].data[1] = allEdges[i].data[1];
    localEdges[i].data[2] = allEdges[i].data[2];
}

然后我需要按数据[2]字段的升序(按上升边权重)对localEdges的内容进行排序。我的比较功能是:

int myComp (const void *a, const void *b)
{
    const edge_t * ptr_a = (const edge_t *)a;
    const edge_t * ptr_b = (const edge_t *)b;
    return ptr_b->data[2] < ptr_a->data[2];
}

该函数的调用如下:

qsort(localEdges, n, sizeof(edge_t), myComp);

然而,这不起作用。已处理的localEdges数组错误地放置了一些数据。例如:

localEdges[0].data[2] = 1
localEdges[1].data[2] = 2
localEdges[2].data[2] = 1
localEdges[3].data[2] = 2
localEdges[4].data[2] = 3
localEdges[5].data[2] = 3
localEdges[6].data[2] = 4

应该是:

localEdges[0].data[2] = 1
localEdges[1].data[2] = 1
localEdges[2].data[2] = 2
localEdges[3].data[2] = 2
localEdges[4].data[2] = 3
localEdges[5].data[2] = 3
localEdges[6].data[2] = 4

我想有一些指针,但我对它们并不十分自信。

有什么建议吗?我会感谢你的帮助。

3 个答案:

答案 0 :(得分:3)

简而言之:您的比较功能是错误的。引用a qsort() manual

  

如果第一个参数被认为分别小于,等于或大于第二个参数,则比较函数必须返回小于,等于或大于零的整数。如果两个成员比较相等,则它们在排序数组中的顺序是未定义的。

因此,如果您返回0,则认为这两个元素相等。

return ptr_b->data[2] < ptr_a->data[2];

如果0中的值大于*ptr_b中的值,则此行返回*ptr_a

正确的方法如下:

int myComp (const void *a, const void *b)
{
    const edge_t * ptr_a = (const edge_t *)a;
    const edge_t * ptr_b = (const edge_t *)b;
    if (ptr_a->data[2] < ptr_b->data[2]) return -1;
    if (ptr_a->data[2] > ptr_b->data[2]) return 1;
    return 0;
}

答案 1 :(得分:2)

来自C标准(7.22.5.2 qsort功能)

  

3数组的内容按升序排序   到compar指向的比较函数,调用它   两个指向被比较对象的参数。 功能   如果,则返回小于,等于或大于零的整数   第一个参数被认为分别小于,相等   到,或大于第二个。

因此定义函数,例如以下方式

int myComp (const void *a, const void *b)
{
    const edge_t * ptr_a = (const edge_t *)a;
    const edge_t * ptr_b = (const edge_t *)b;

    return ( ptr_b->data[2] < ptr_a->data[2] ) - ( ptr_a->data[2] < ptr_b->data[2] );
}

答案 2 :(得分:0)

您的比较器功能似乎未正确实现。它永远不会返回负面结果,只是将bool值(比较操作)转换为0和1.你能尝试类似的东西:

int myComp (const void *a, const void *b)
{
    const edge_t * ptr_a = (const edge_t *)a;
    const edge_t * ptr_b = (const edge_t *)b;
    return (ptr_b->data[2] < ptr_a->data[2]) ? -1 : 
        (ptr_b->data[2] > ptr_a->data[2]) ? 1 : 0;
}