Πώς να βρείτε αποτελεσματικά τελευταίο κλειδί και την αξία σε GTree

ψήφοι
0

Θα πρέπει να αναπτύξουν μια σειρά από λειτουργίες για την επέκταση glib2 GTreeμε:

  • βρείτε το πρώτο στοιχείο
  • βρείτε τον περασμένο
  • βρείτε το πλησιέστερο (δάπεδο, ceil, μεγαλύτερη λιγότερο από ό, τι, τουλάχιστον μεγαλύτερο από)

Η εύρεση πρώτο είναι εύκολο. Μπορείτε απλά να σταματήσει την g_tree_foreach()calback μετά την πρώτη. Αλλά πώς να βρει το τελευταίο στοιχείο , χωρίς να διατρέχει το σύνολο του δέντρου ;

Νόμιζα ότι θα μπορούσε να χρησιμοποιήσει g_tree_search()με επιστροφή κλήσης που κρατά την επιστροφή θετική τιμή μέχρι να βρεθεί, αλλά πώς μπορώ να ξέρω ότι είμαι σήμερα στην τελευταία στοιχείου;

#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;
}
Δημοσιεύθηκε 03/06/2017 στις 21:33
πηγή χρήστη
Σε άλλες γλώσσες...                            


1 απαντήσεις

ψήφοι
0

Δεν ήθελα να εφαρμόσουν πλήρως το δικό μου δέντρο, γιατί ήθελε να εκτελέσει προηγμένη αναζήτηση σε GTreeπεριπτώσεις που έλαβε από τον κωδικό 3ου μέρους.

Αντ 'αυτού σκέφτηκα ότι Glib συγγραφείς θα αλλάξει ελάχιστα τις εσωτερικές τους δομές αυτές τις μέρες και ότι θα μπορούσα να χρησιμοποιήσω άμεσα τα χωράφια τους.

Το αποτέλεσμα είναι η εκτεταμένη έκδοση της εσωτερικής λειτουργίας g_tree_find_node()από gtree.c. Πρόσθεσα δύο παραμέτρους για να ελέγξετε αν θέλω κατ 'αρχάς, την τελευταία ή τον πλησιέστερο κόμβο. Ο αλγόριθμος για την κοντινότερη κόμβων διαφέρει από της Java TreeMap, γιατί ο κόμβος μας δεν έχει ένα δείκτη προς τη μητρική της. Πλήρης κώδικα με τη δοκιμή μονάδα είναι εδώ: 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;
                }
        }
}

Για καλύτερη απόδοση είναι δυνατή η χρήση μακροεντολές προεπεξεργαστή αντί των δύο νέων παραμέτρων, αντικαταστήστε ifμε #ifκαι περιλαμβάνουν τα bits header πολλές φορές.

Απαντήθηκε 04/07/2017 στις 17:47
πηγή χρήστη

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