2013-08-09 4 views
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-деревьев и сортировка массива указателей с использованием 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 не может помочь), полезно подумать о том, как работает 0sqsort. qsort ничего не знает о типе или . Представление сортируемых данных: он просто перетасовывает около небольшие куски памяти. (Все, что он знает о кусках, это их размер, , который вы указываете в третьем аргументе qsort.) Чтобы определить, нужно ли заменять два блока , qsort вызывает вашу функцию сравнения. (Для того, чтобы поменять их, он использует эквивалент тетсру.)

Но мне интересно, если есть какая-то альтернатива (используя stdlib qsort), чтобы избежать необходимости поддерживать две функции сравнения (один для AVL, а другой для void **)

ответ

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 функции, но вы не повторяетесь, и их легче поддерживать.

EDIT: Как С.Л. сказал, что если вы используете C99, cmp может быть static inline функция.

+2

Определите 'cmp' как' static inline' для дополнительной производительности ('gnu99 ++' standard) –

+0

@SergeyL. Да, ты прав, спасибо! :) – nouney

1

вы не можете использовать точно такую ​​же функцию, но вы можете определить второе в терминах первой:

int cmp2(const void *pa, const void *pb) 
{ 
    return cmp(*(void **)pa, *(void **)pb); 
} 
Смежные вопросы