GTree из примера Глиба - PullRequest
0 голосов
/ 16 апреля 2020

Итак, у меня есть структура, которая выглядит так:

typedef struct sales
{
    int* salesN;
    int* salesP;
}*Sales;

И у меня будет много строк, таких как char * product, которые я хочу связать с этой структурой И структура GTree от Glib кажется хорошим вариантом с точки зрения эффективности.

По сути, я хочу, чтобы ключ был строкой, а значение - структурой. Я также хочу, чтобы они сортировались в алфавитном порядке, поэтому я предполагаю, что функция сравнения должна быть чем-то похожим на strcmp.

Но у меня проблемы с запуском и инициализацией GTree. Я был бы очень признателен, если бы кто-нибудь дал мне быстрый пример кода, как инициализировать, как вставлять и как искать и изменять некоторые значения.

Заранее большое спасибо.

1 Ответ

0 голосов
/ 16 апреля 2020

Во-первых, нам нужно исправить объявление структуры. Это typedef <type declaration> <name>. Так что не *Sales, а просто Sales.

typedef struct sales
{
    int* salesN;
    int* salesP;
} Sales;

Теперь мы следуем инструкциям документации GTree , сначала мы создаем дерево и сообщаем ему, как сравнивать ключи.

GTree *sales_tree = g_tree_new(g_str_equal);

Мы не можем использовать strcmp, потому что у него неправильная подпись. Вместо этого мы используем функции, найденные в Ха sh Таблицах .

Теперь мы делаем продажу и вставляем ее с ключом. Все это делается с помощью указателей, ключей и значений.

// Make a Sale
int n = 23;
int p = 42;
Sales sale = { .salesN = &n, .salesP = &p };

// Insert it as "The Stuff".
const char *key = "The Stuff";
g_tree_insert(sales_tree, &key, &sale);

И мы можем извлечь его как указатель, используя тот же ключ.

Sales *found = g_tree_lookup(sales_tree, key);
printf("n %d, p %d\n", *found->salesN, *found->salesP);

И, наконец, очистить дерево, чтобы избежать утечки памяти.

g_tree_destroy(sales_tree);

g_tree_foreach работает очень похоже на q_sort_r. Требуется указатель на функцию типа GTraverseFunc, который будет вызываться на каждом узле. Если он возвращает true, обход прекращается.

g_tree_foreach принимает дополнительный аргумент, который будет передаваться при каждом вызове функции. Это позволяет хранить информацию во время обхода без использования глобальных переменных.

Например, вот небольшая функция, которая использует GPtrArray для сбора списка всех значений в дереве .

gboolean find_all_nodes(gpointer key, gpointer value, gpointer all) {
    g_ptr_array_add(all, value);
    return FALSE;
}

Затем мы обходим дерево, используя нашу функцию следующим образом.

GPtrArray *all = g_ptr_array_new();
g_tree_foreach(sales_tree, find_all_nodes, all);

И мы можем посмотреть на то, что мы захватили в массиве указателей, будучи уверенными, что освободим его, как только мы с этим покончено.

    for( int i = 0; i < all->len; i++ ) {
        Sales *s = g_ptr_array_index(all, i);
        printf("n %d, p %d\n", *s->salesN, *s->salesP);
    }
    g_ptr_array_free(all, TRUE);
...