简体   繁体   English

Qsort()在结构上不起作用

[英]Qsort() doesn't work on a struct

I'm currently implementing some algorithm on graphs and I use a struct to keep the information about every edge in the graph: its source vertex, its destination vertex and its weight. 我目前正在对图形实施某种算法,并使用一种结构来保留有关图形中每个边的信息:其源顶点,目标顶点及其权重。

I have my struct declared as following: 我的结构声明如下:

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

Then I create a variable pointer and allocate memory for n structs, where n is a number of edges in a graph: 然后,我创建一个变量指针并为n结构分配内存,其中n是图中的许多边:

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

Then I fill up struct localEdges with the values of another struct allEdges of the same type: 然后,我填补结构localEdges与其他结构的值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];
}

And then I need to sort the contents of localEdges by ascending order of data[2] field (by ascending edge weight). 然后,我需要按data [2]字段的升序(按边缘权重递增)对localEdges的内容进行排序。 My compare function is this: 我的比较功能是这样的:

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];
}

And the call for the function is the following: 该函数的调用如下:

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

However, that doesn't work. 但是,这不起作用。 The processed localEdges array has some data placed wrongly. 处理后的localEdges数组放置了一些错误的数据。 For example: 例如:

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

When it should be: 什么时候应该是:

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

I guess there is something with pointers, but I'm not quite confident with them. 我猜有一些指针,但是我对它们不太自信。

Any suggestions? 有什么建议么? I'll Appreciate your help. 我会感谢您的帮助。

In short: Your comparison function is wrong. 简而言之:您的比较功能是错误的。 Citing a qsort() manual : 引用qsort()手册

The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. 如果第一个参数被认为分别小于,等于或大于第二个参数,则比较函数必须返回小于,等于或大于零的整数。 If two members compare as equal, their order in the sorted array is undefined. 如果两个成员比较相等,则它们在排序数组中的顺序是不确定的。

So, if you're returning 0 , the two elements are considered equal. 因此,如果您返回0 ,则将这两个元素视为相等。

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

This line does return 0 if the value in *ptr_b is greater than that in *ptr_a . 这条线不会返回0 ,如果在值*ptr_b比更大*ptr_a

The correct way to do it is as follows: 正确的方法如下:

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;
}

From the C Standard (7.22.5.2 The qsort function) 来自C标准(7.22.5.2 qsort函数)

3 The contents of the array are sorted into ascending order according to a comparison function pointed to by compar, which is called with two arguments that point to the objects being compared. 3根据compar所指向的比较函数,将数组的内容按升序排序,该函数通过两个指向被比较对象的自变量进行调用。 The function shall return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. 如果第一个参数被认为分别小于,等于或大于第二个参数,则该函数应返回小于,等于或大于零的整数。

Thus define the function for example the following way 从而通过以下方式例如定义功能

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] );
}

It seems your comparer function is incorrectly implemented. 看来您的比较器功能未正确实现。 It never returns negative result, just bool value (comparison operation) converted to 0 and 1. Could you try something like that: 它从不返回负结果,只是布尔值(比较操作)转换为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;
}

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

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