qsort с функцией компаратора разные

Мне нужна помощь с функцией СРАВНИТЬ в qsort. Сравните массив G-> orden, но сравнивая с элементом порядка, который служит индексом в другом массиве, и с тем, как вставить G в compare.

struct VerticeSt {
    u32 nombre;
    u32 color;
    u32 grado;
    u32 *vecinos;
};
struct GrafoSt {
    u32 n;
    u32 m;
    u32 nc;
    u32 delta;
    Vertices v;
    u32 *orden;
};

int Compare(const void* a, const void* b) {
     u32* x1 = (u32*) a;
     u32* x2 = (u32*) b;
     if(G->v[G->orden[x1]] < G->v[G->orden[x2]]) 
         return -1;
     else
     .
     .
     .
}
qsort(G->orden, G->n, sizeof(u32), Compare);

person Facundo Zerpa    schedule 13.04.2019    source источник
comment
Подскажите, пожалуйста, что вы получаете вместо чего?   -  person Maifee Ul Asad    schedule 13.04.2019
comment
Вы используете указатель в качестве индекса массива? Ваш компилятор не жалуется на это?   -  person Shawn    schedule 13.04.2019
comment
Я не могу получить никаких результатов, так как не могу вызвать функцию СРАВНЕНИЕ с параметрами, отличными от порядка G- ›. Элементы G- ›порядка [i] послужили бы мне указанием в другом расположении, скорее в G-› v [G- ›order [i]]. Я до сих пор не могу справиться с этой идеей. Я не могу решить, что Compare может принимать меня в дополнение к двум const a b, a Grafo G.   -  person Facundo Zerpa    schedule 13.04.2019
comment
Сравните в qsort и получите два параметра: const void a, const void b. Мне нужно, чтобы Сравните полученные параметры const void a const void b Grafo G.   -  person Facundo Zerpa    schedule 13.04.2019
comment
Если G не является частью a и b, то единственный способ получить доступ к G - это сделать G статической переменной области файла или просто старой простой глобальной переменной.   -  person user3386109    schedule 13.04.2019
comment
typedef для Vertices отсутствует - вы делаете его указателем: typedef struct VerticeSt *Vertices;? Есть ли у вас qsort_r()? Похоже, это вам очень поможет. Остерегайтесь, версия qsort_r() в Linux (библиотека GNU C) отличается от версии в * BSD и macOS - они имеют эквивалентную функциональность, но разный порядок аргументов.   -  person Jonathan Leffler    schedule 13.04.2019


Ответы (1)


Предполагая (из вашего обращения к qsort()), что G->orden указывает на базу массива значений типа u32 с длиной G->n, тогда значения, переданные вашей функции сравнения, будут указателями на элементы этого массива. Ваша Compare() функция должна преобразовать переданные ей void* указатели в указатели на тип, о котором она знает, а затем разыменовать их, чтобы получить фактические значения, которые она будет сравнивать.

Вот короткая программа, которая показывает все это в действии:

#include <stdio.h>
#include <stdlib.h>

typedef unsigned long u32;

int Compare(const void* a, const void* b) {
    u32 x1 = *(u32*)a;   // Get the array element that a points to
    u32 x2 = *(u32*)b;   // Get the array element that b points to

    if (x1 < x2)         // Compare the values and return result
        return -1;
    else if (x1 == x2)
        return 0;
    else return 1;
}

void printArray(char* label, u32* a, int n) {
    printf("%s", label);
    for (int i = 0; i < n; i++)
        printf("\t%lu", (unsigned long)a[i]);
    printf("\n");
}

int main(int argc, const char* argv[]) {
    u32 array[5] = {9, 3, 27, 18, 6};
    printArray("unsorted: ", array, 5);
    qsort(array, 5, sizeof(u32), Compare);
    printArray("  sorted: ", array, 5);
    return 0;
}

И вот результат:

unsorted:   9   3   27  18  6
  sorted:   3   6   9   18  27

Сравните в qsort и получите два параметра: const void a, const void b. Мне нужно, чтобы Compare получил три параметра const void a const void b Grafo G.

В таком случае qsort(), вероятно, вам не подходит. Также есть qsort_r() и qsort_b(). qsort_r() принимает дополнительный параметр void*, который также передается в функцию сравнения, и это звучит наиболее близко к тому, что вам нужно - вы можете передать указатель на свой G в этом параметре. qsort_b() принимает блок сравнения (также известный как закрытие) вместо функции, и этот блок может захватывать контекст от вызывающей стороны.

person Caleb    schedule 13.04.2019
comment
Вы также можете просто return (x1 > x2) - (x1 < x2); То же самое, только короче. - person David C. Rankin; 13.04.2019
comment
Вы также можете return (long)x1 - (long)x2; - person selbie; 13.04.2019
comment
@ DavidC.Rankin Мне это нравится! Но я думаю, что для целей примера, если сделать это более подробно, лучше проиллюстрировать общий случай ... Ценности OP (или будущего читателя) могут быть чем-то совершенно другим. - person Caleb; 13.04.2019
comment
@selbie (long)x1 - (long)x2 может привести к переполнению, что приведет к UB и, конечно, неверным результатам с большими значениями. (x1 > x2) - (x1 < x2) не имеет такой проблемы. - person chux - Reinstate Monica; 13.04.2019