Nasıl verimli GTree son anahtarı ve değerini bulmak için

oy
0

Ben genişletmek için işlevler kümesi geliştirmek gerekir glib2 GTreeile:

  • İlk eleman bulmak
  • geçen bulmak
  • En yakın bulmak (zemin, hücrelerinin,, büyük, küçüktür az daha büyüktür)

İlk bulmak kolaydır. Sadece durdurmak g_tree_foreach()ilk sonra calback. Ama nasıl son maddeyi bulmak için bütün ağaç geçme olmadan ?

Ben kullanabileceğini düşündüm g_tree_search()bulana kadar pozitif bir değer dönen tutan bir geri arama ile, ama nasıl ben son öğe şu anda olduğum anlarım?

#include <stdio.h>
#include <sys/types.h>
#include <string.h>

#include <glib.h>

static
gint compare_int(gconstpointer p1, gconstpointer p2) {
    int i1 = GPOINTER_TO_INT(p1);
    int i2 = GPOINTER_TO_INT(p2);
    //printf(%d %d\n, i1, i2);
    return i1 == i2 ? 0 : i1 > i2 ? 1 : -1;
}


static
gboolean traverse(gpointer key, gpointer value, gpointer data) {
    //int ikey = GPOINTER_TO_INT(key);
    const char *sval = (const char *)value;
    printf(%s\n, sval);
    return FALSE;
}

static
gint find_last(gconstpointer p, gpointer user_data) {
    return 1;
}

static inline const char *NULS(const char *s) {
    return s ? s : NULL;
}

int main(int argc, char *argv[]) {
    GTree *tree = g_tree_new(compare_int);
    g_tree_insert(tree, GINT_TO_POINTER(10), ten);
    g_tree_insert(tree, GINT_TO_POINTER(-99), minus ninety-nine);
    g_tree_insert(tree, GINT_TO_POINTER(8), eight);
    g_tree_foreach(tree, traverse, NULL);
    printf(=======\n%s\n, NULS((const char*)g_tree_search(tree, (GCompareFunc)find_last, NULL)));
    return 0;
}
Oluştur 03/06/2017 saat 21:33
kaynak kullanıcı
Diğer dillerde...                            


1 cevaplar

oy
0

Ben gelişmiş arama gerçekleştirmek istediğim için, tamamen kendi ağacını uygulamak istemedi GTree3. taraf kodundan alınan örneklerde.

Onun yerine Glib yazarlar pek bugünlerde kendi iç yapılarını değiştirip doğrudan tarlalarını kullanabileceği düşündük.

Sonuç iç fonksiyonun genişletilmiş versiyonudur g_tree_find_node()dan gtree.c. Ben geçen veya en yakın düğüm, ilk isteyip istemediğinizi denetlemek için iki parametre eklendi. En yakın düğümler için algoritma java yıllardan farklı TreeMapbizim düğüm kendi üst bir işaretçi olmadığı için. Birim testi ile tam kod buradadır: gtreeex.c.

typedef enum {
    FIND_EXACT = 0,
    FIND_FLOOR = 0x2,
    FIND_CEIL  = 0x20,
    FIND_LOWER = (FIND_FLOOR + 1),
    FIND_HIGHER = (FIND_CEIL + 1)
} find_mode;

static GTreeNode *
g_tree_find_node_ex (GTree        *tree,
                  gconstpointer key,
                  GCompareDataFunc key_compare,
                  find_mode mode
                  )
{
    GTreeNode *node;
    gint cmp;
    GTreeNode *last_lesser_node = NULL;
    GTreeNode *last_greater_node = NULL;

    node = tree->root;
    if (!node)
        return NULL;

    while (1)
        {
            cmp = key_compare (key, node->key, tree->key_compare_data);
            if (cmp == 0) {
                if (mode == FIND_LOWER) {
                    cmp = -1;
                } else if (mode == FIND_HIGHER) {
                    cmp = 1;
                } else {
                    return node;
                }
            }

            if (cmp < 0)
                {
                    if (!node->left_child) {
                        if ( (mode & FIND_FLOOR) ) {
                            return last_lesser_node; /* can be null */
                        }
                        if ( (mode & FIND_CEIL) ) {
                            return node;
                        }
                        return NULL;
                    }

                    last_greater_node = node;
                    node = node->left;
                }
            else
                {
                    if (!node->right_child) {
                        if ( (mode & FIND_CEIL) ) {
                            return last_greater_node; /* can be null */
                        }
                        if ( (mode & FIND_FLOOR) ) {
                            return node;
                        }
                        return NULL;
                    }

                    last_lesser_node = node;
                    node = node->right;
                }
        }
}

Daha iyi performans için bu iki yeni parametrelerin yerine önişlemci makroları kullanmak yerine mümkün ifolan #ifve bit birden çok kez başlık bulunmaktadır.

Cevap 04/07/2017 saat 17:47
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more