Jak efektivně hledat poslední klíč a hodnotu GTree

hlasů
0

Potřebuji vytvořit sadu funkcí, které se rozprostírají glib2 GTreena:

  • najít první prvek
  • najít poslední
  • najít nejbližší (podlahu, horní limit, největší méně než alespoň větší než)

Nalezení První z nich je snadné. Vy prostě zastavit g_tree_foreach()Calback po prvním. Ale jak najít poslední prvek bez křížení celý strom ?

Myslel jsem, že bych mohl použít g_tree_search()s zpětné volání, která udrží vrací kladnou hodnotu, až našel, ale jak mám vědět, že jsem v současné době na poslední prvek?

#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;
}
Položena 03/06/2017 v 21:33
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
0

Nechtěl jsem, aby plně realizovat svůj vlastní strom, protože jsem chtěl provést pokročilé vyhledávání na GTreepřípadech obdržela od kódu třetí strany.

Místo toho jsem si myslel, že glib Autoři by stěží změní své vnitřní struktury v těchto dnech, a že jsem mohl přímo použít svá pole.

Výsledkem je prodloužená verze vnitřní funkce g_tree_find_node()z gtree.c. Přidal jsem dva parametry pro kontrolu, zda chci, první, poslední nebo nejbližší uzel. Algoritmus pro nejbližších uzlů odlišuje od Javy TreeMap, protože naše uzel nemá ukazatel na své mateřské společnosti. Úplný kód se zkouškou každého jednotlivého výrobku je zde: 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;
                }
        }
}

Pro lepší výkon je možné použít preprocesoru makra namísto dvou nových parametrů, nahradí ifse #ifa zahrnují bity hlavičky vícekrát.

Odpovězeno 04/07/2017 v 17:47
zdroj uživatelem

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