C # δυαδικά δέντρα και Λεξικά

ψήφοι
15

Είμαι αγωνίζονται με την έννοια του πότε να χρησιμοποιούν δυαδικά δέντρα αναζήτησης και πότε να χρησιμοποιούν λεξικά.

Στην αίτησή μου έκανα ένα μικρό πείραμα που χρησιμοποίησε η βιβλιοθήκη C5 TreeDictionary(η οποία πιστεύω ότι είναι ένα κόκκινο-μαύρο δυαδικό δένδρο αναζήτησης), και η C # λεξικό. Το λεξικό ήταν πάντα πιο γρήγορα στο add / βρείτε επιχειρήσεις και επίσης χρησιμοποιείται πάντα λιγότερο χώρο στη μνήμη. Για παράδειγμα, σε 16.809 <int, float>συμμετοχές, το λεξικό που χρησιμοποιείται 342 KiB, ενώ το δέντρο που χρησιμοποιείται 723 KiB.

Νόμιζα ότι η BST που έπρεπε να είχαν περισσότερη μνήμη αποτελεσματική, αλλά φαίνεται ότι ένα κόμβο του δέντρου απαιτεί περισσότερα bytes από μία είσοδο σε ένα λεξικό. Αυτό που δίνει; Υπάρχει ένα σημείο στο οποίο BST είναι καλύτερη από ό, τι λεξικά εκεί;

Επίσης, ως δευτερεύον ζήτημα, Ξέρει κανείς αν υπάρχει ένα πιο γρήγορο + περισσότερη μνήμη αποτελεσματική δομή δεδομένων για την αποθήκευση <int, float>ζεύγη για λεξικού πρόσβαση είδος, είτε από από τις προαναφερθείσες δομές;

Δημοσιεύθηκε 28/01/2010 στις 02:46
πηγή χρήστη
Σε άλλες γλώσσες...                            


6 απαντήσεις

ψήφοι
1

Κατά τη γνώμη μου κάνεις μια πρόωρη βελτιστοποίηση.

Αυτό που θα πρότεινα σε σας είναι να δημιουργήσετε μια διεπαφή για να απομονώσει το οποίο δομής είστε πραγματικά χρησιμοποιείτε, και στη συνέχεια να εφαρμόσει το περιβάλλον χρησιμοποιώντας το λεξικό (το οποίο φαίνεται να λειτουργεί καλύτερα).

Εάν η μνήμη / απόδοση γίνεται ένα ζήτημα (που κατά πάσα πιθανότητα δεν θα για 20Κ αριθμούς), τότε μπορείτε να δημιουργήσετε άλλες εφαρμογές περιβάλλον, και να ελέγξετε ποια λειτουργεί καλύτερα. Δεν θα χρειαστεί να αλλάξει σχεδόν τίποτα στο υπόλοιπο του κώδικα (με εξαίρεση το οποίο εφαρμογή που χρησιμοποιείτε).

Απαντήθηκε 28/01/2010 στις 03:26
πηγή χρήστη

ψήφοι
1

Αυτό έχει νόημα ότι ένας κόμβος δέντρο θα απαιτήσει περισσότερο αποθηκευτικό χώρο από ό, τι ένα λεξικό εισόδου. Ένα δυαδικό κόμβο του δένδρου πρέπει να αποθηκεύσετε την τιμή και τόσο το αριστερό και το δεξί υποδένδρων. Η γενική Dictionary<TKey, TValue>υλοποιείται ως ένα πίνακα κατακερματισμού που - υποθέτω - είτε χρησιμοποιεί μια συνδεδεμένη λίστα για κάθε κάδο (τιμή συν ένα δείκτη / αναφοράς) ή κάποιου είδους χαρτογράφηση (μόνο η αξία). Θα πρέπει να έχουν μια ματιά σε ανακλαστήρα για να είναι σίγουρος, αλλά για τους σκοπούς του παρόντος ερώτημα δεν νομίζω ότι είναι τόσο σημαντικό.

Ο αραιές ο πίνακας hash, η λιγότερο αποτελεσματική από την άποψη της αποθήκευσης / μνήμης. Εάν δημιουργήσετε ένα πίνακα κατακερματισμού (λεξικό) και θα ξεκινήσουν την ικανότητά της στο 1 εκατομμύριο, και γεμίστε μόνο με 10.000 στοιχεία, τότε είμαι σίγουρος ότι θα τρώνε πολύ περισσότερη μνήμη από μια BST με 10.000 κόμβους.

Παρόλα αυτά, δεν θα ανησυχείτε για τίποτα από όλα αυτά, αν το ποσό των κόμβων / κλειδιών είναι μόνο κατά χιλιάδες. Αυτό πρόκειται να μετρηθεί στα kilobytes, σε σύγκριση με gigabytes μνήμης RAM.


Αν η ερώτηση είναι «γιατί θα θέλετε να χρησιμοποιήσετε ένα δυαδικό δέντρο αντί για ένα πίνακα κατακερματισμού;» Στη συνέχεια, η καλύτερη απάντηση είναι ΙΜΟ ότι τα δυαδικά δέντρα διέταξε ενώ πίνακας κατακερματισμού δεν είναι. Μπορείτε να αναζητήσετε μόνο έναν πίνακα κατακερματισμού για τα κλειδιά που είναι ακριβώς ίση με κάτι? με ένα δέντρο, μπορείτε να αναζητήσετε ένα εύρος τιμών, το πλησιέστερο αξία, κλπ Αυτή είναι μια πολύ σημαντική διάκριση, αν θέλετε να δημιουργήσετε ένα ευρετήριο ή κάτι παρόμοιο.

Απαντήθηκε 28/01/2010 στις 03:39
πηγή χρήστη

ψήφοι
0

Η διεπαφή για ένα δέντρο και ένα πίνακα κατακερματισμού (που υποθέτω είναι αυτό που λεξικό σας με βάση ένα) θα πρέπει να είναι πολύ παρόμοια. Πάντα περιστρέφονται γύρω από πληκτρολογηθεί αναζητήσεις.

Είχα πάντα πίστευα ένα λεξικό ήταν καλύτερη για τη δημιουργία πράγματα μία φορά και, στη συνέχεια, στη συνέχεια, κάνει πολλά αναζητήσεις σε αυτό. Ενώ ένα δέντρο ήταν καλύτερα αν ήταν το τροποποιώντας σημαντικά. Ωστόσο, δεν ξέρω πού πήρα αυτή την ιδέα έναντι.

(Λειτουργική γλώσσες χρησιμοποιούν συχνά τα δέντρα ως βάση για τους συλλογές, όπως μπορείτε να χρησιμοποιήσετε ξανά το μεγαλύτερο μέρος του δέντρου, αν κάνετε μικρές τροποποιήσεις της).

Απαντήθηκε 28/01/2010 στις 03:40
πηγή χρήστη

ψήφοι
0

Δεν είστε συγκρίνει «τα μήλα με μήλα», μια BST θα σας δώσει μια εντολή εκπροσώπησης, ενώ ένα λεξικό σας επιτρέπει να κάνετε μια αναζήτηση για ένα ζεύγος κλειδιών αξίας (στην περίπτωσή σας).

Δεν θα περίμενε κανείς πολύ το μέγεθος του αποτύπωμα μνήμης μεταξύ των 2, αλλά το λεξικό θα σας δώσει ένα πολύ πιο γρήγορα αναζήτησης. Για να βρείτε ένα στοιχείο σε μια BST που (ενδεχομένως) πρέπει να διασχίσει ολόκληρο το δέντρο. Αλλά για να γίνει μια dictnary αναζήτηση μπορείτε απλά αναζήτηση με βάση το κλειδί.

Απαντήθηκε 28/01/2010 στις 04:05
πηγή χρήστη

ψήφοι
8

Νόμιζα ότι η BST που έπρεπε να είχαν περισσότερη μνήμη αποτελεσματική, αλλά φαίνεται ότι ένα κόμβο του δέντρου απαιτεί περισσότερα bytes από μία είσοδο σε ένα λεξικό. Αυτό που δίνει; Υπάρχει ένα σημείο στο οποίο BST είναι καλύτερη από ό, τι λεξικά εκεί;

Έχω προσωπικά ποτέ ακούσει για μια τέτοια αρχή. Ακόμα ακόμα, μόνο μια γενική αρχή του, δεν είναι κατηγορηματική γεγονός χαραγμένη στο ύφασμα του σύμπαντος.

Σε γενικές γραμμές, λεξικά είναι πραγματικά ακριβώς ένα φανταχτερό περιτύλιγμα γύρω από μια σειρά από συνδεδεμένες λίστες. Μπορείτε να εισαγάγετε στο λεξικό κάτι σαν:

LinkedList<Tuple<TKey, TValue>> list =
    internalArray[internalArray % key.GetHashCode()];
if (list.Exists(x => x.Key == key))
    throw new Exception("Key already exists");
list.AddLast(Tuple.Create(key, value));

Έτσι του σχεδόν O (1) λειτουργία. Το λεξικό χρησιμοποιεί O (internalArray.Length + n) μνήμη, όπου το η είναι αριθμός από αντικείμενα της συλλογής.

Σε γενικές γραμμές BSTs μπορεί να υλοποιηθεί ως εξής:

  • συνδεδεμένο-λίστες, οι οποίες χρησιμοποιούν O (n) χώρο, όπου Ν είναι ο αριθμός αντικείμενα της συλλογής.
  • συστοιχίες , οι οποίες χρησιμοποιούν O (2 h - n) χώρο όπου h είναι το ύψος του δέντρου και το η είναι ο αριθμός των στοιχείων στη συλλογή.
    • Από κόκκινο-μαύρο δέντρα έχουν ένα περιορισμένο ύψος O (1.44 * Ν), μια υλοποίηση συστοιχία πρέπει να έχουν ένα περιορισμένο χρήση μνήμης του περίπου O (2 1.44n - n)

Οι πιθανότητες είναι, η C5 TreeDictionary υλοποιείται με τη χρήση πινάκων, η οποία είναι πιθανώς υπεύθυνη για τη σπατάλη χώρου.

Αυτό που δίνει; Υπάρχει ένα σημείο στο οποίο BST είναι καλύτερη από ό, τι λεξικά εκεί;

Λεξικά έχει κάποιες ανεπιθύμητες ιδιότητες:

  • Δεν μπορεί να είναι αρκετά continugous μπλοκ της μνήμης για να κρατήσει λεξικό σας, ακόμα και αν οι απαιτήσεις μνήμης του είναι πολύ μικρότερη από ό, τι η συνολική διαθέσιμη μνήμη RAM.

  • Αξιολογώντας τη συνάρτηση κατακερματισμού μπορεί να πάρει ένα αυθαίρετα μεγάλο χρονικό διάστημα. Χορδές, για παράδειγμα, χρήση ανακλαστήρα για να εξετάσει τη System.String.GetHashCodeμέθοδο - θα παρατηρήσετε τον κατακερματισμό μια σειρά παίρνει πάντα O (n) χρόνο, πράγμα που σημαίνει ότι μπορεί να πάρει πολύ χρόνο για πολύ καιρό χορδές. Από την πλευρά, συγκρίνοντας χορδές για ανισότητας σχεδόν πάντα πιο γρήγορα από ό, τι κατακερματισμού, δεδομένου ότι μπορεί να απαιτούν κοιτάζοντας μόνο τις πρώτες χαρακτήρες. Της εξ ολοκλήρου δυνατό για ένθετα δέντρο να είναι ταχύτερη από ό, τι λεξικό ένθετα αν αξιολόγησης κωδικό hash παίρνει πάρα πολύ καιρό.

    • Int32 της GetHashCodeμεθόδου είναι κυριολεκτικά ακριβώς return this, έτσι θέλετε να hardpressed να βρείτε μια περίπτωση όπου ένας hashtable με τα κλειδιά int είναι πιο αργή από ό, τι ένα λεξικό δέντρο.

RB δέντρα έχουν κάποιες επιθυμητές ιδιότητες:

  • Μπορείτε να βρείτε / αφαίρεση των στοιχείων Min και Max σε O (log n) χρόνο, σε σύγκριση με το O (n) χρόνο χρησιμοποιώντας ένα λεξικό.

  • Αν ένα δέντρο υλοποιείται ως συνδεδεμένη λίστα και όχι μια σειρά, το δέντρο είναι συνήθως περισσότερο χώρο αποδοτική από ό, τι ένα λεξικό.

  • Ομοίως, γελοία εύκολο να γράψει αμετάβλητο εκδόσεις των δέντρων που υποστηρίζουν την εισαγωγή / αναζήτηση / διαγραφή σε O (log n) χρόνο. Λεξικά δεν προσαρμόζονται καλά στο αμετάβλητο, δεδομένου ότι θα πρέπει να αντιγράψετε το σύνολο του εσωτερικού πίνακα για κάθε λειτουργία (στην πραγματικότητα, θα έχουν δει κάποια σειρά με βάση τις εφαρμογές των αμετάβλητων δέντρα δάχτυλο, ένα είδος γενικής χρήσης λεξικού δομή δεδομένων, αλλά η εφαρμογή είναι πολύ συγκρότημα).

  • Μπορείτε να διασχίζουν όλα τα στοιχεία σε ένα δέντρο σε ταξινομημένη σειρά σε συνεχή χώρο και O (n) χρόνο, ενώ τότε θα πρέπει να πετάξει ένα πίνακα κατακερματισμού σε μια σειρά και να ταξινομήσετε να πάρει το ίδιο αποτέλεσμα.

Έτσι, η επιλογή της δομής δεδομένων εξαρτάται πραγματικά από το τι ιδιότητες που χρειάζεστε. Αν θέλετε απλά μια μη διατεταγμένη τσάντα και μπορεί να εγγυηθεί ότι η συνάρτηση κατακερματισμού σας να αξιολογήσει γρήγορα, να πάει με .Net λεξικό. Αν χρειάζεστε μια διατεταγμένη τσάντα ή έχουν μια λειτουργία αργή λειτουργία hash, πάει με TreeDictionary.

Απαντήθηκε 28/01/2010 στις 04:16
πηγή χρήστη

ψήφοι
0

Μια ισορροπημένη BST είναι προτιμότερο αν χρειαστεί να προστατεύσει τη δομή των δεδομένων σας από την λανθάνουσα κατάσταση αιχμές και συγκρούσεις hash επιθέσεις.

Ο πρώην συμβαίνει όταν μια συστοιχία υποστηριζόμενη δομή αναπτύσσεται ένας παίρνει αλλάξει μέγεθος, το τελευταίο είναι ένα αναπόφευκτο ιδιότητα του hashing αλγορίθμου ως προβολή από άπειρο χώρο σε περιορισμένο ακέραιος εύρος.

Ένα άλλο πρόβλημα στο .NET είναι ότι υπάρχει ΑΕ, και με ένα αρκετά μεγάλο λεξικό πέσετε σε κατακερματισμό ΑΕ. Σε αυτή την περίπτωση μπορείτε να χρησιμοποιήσετε ένα BST, δίνοντας μια τιμή μεγαλύτερη αλγοριθμικής τάξη πολυπλοκότητας.

Με λίγα λόγια, με μια BST που υποστηρίζεται από το σωρό κατανομή θα έχετε χειρότερη στιγμή περίπτωση O (log (N)), με hashtable μπορείτε να πάρετε O (N) χειρότερη στιγμή υπόθεση.

BST έρχεται στην τιμή των O (log (N)) μέσος χρόνος, χειρότερα τοποθεσία μνήμη cache και κατανομές σωρό, αλλά έχει εγγυήσεις λανθάνουσα κατάσταση και προστατεύεται από το λεξικό επιθέσεις και τον κατακερματισμό της μνήμης.

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

Όσο για το μέγεθος της μνήμης, η τάξη .NET Dictionary`2 είναι περισσότερη μνήμη αποτελεσματική, επειδή αποθηκεύει τα δεδομένα ως off-σωρό συνδεδεμένη λίστα, αξίας οποία απλώς αποθηκεύει και να αντισταθμίσει τις πληροφορίες. BST οφείλει να αποθηκεύει κεφαλίδα αντικειμένου (όπως κάθε κόμβος είναι ένα παράδειγμα της κατηγορίας στο σωρό), δύο δείκτες, και ορισμένες επαυξημένης δεδομένων δέντρο για ισορροπημένη δέντρα. Για παράδειγμα, ένα κόκκινο-μαύρο δέντρο θα χρειαστεί μια boolean ερμηνευθεί ως χρώμα (κόκκινο ή μαύρο). Αυτό είναι τουλάχιστον 6 λέξεις μηχάνημα, αν δεν κάνω λάθος. Έτσι, κάθε κόμβος σε ένα κόκκινο-μαύρο δέντρο στο σύστημα 64-bit είναι τουλάχιστον:

3 λέξεις για την κεφαλίδα = 24 bytes 2 λέξεις για τους δείκτες παιδί = 16 bytes 1 λέξη για το χρώμα = 8 bytes τουλάχιστον 1 λέξη για την τιμή 8+ bytes = 24 + 16 + 8 + 8 = 56 bytes (+8 bytes αν το δέντρο χρησιμοποιεί ένα δείκτη κόμβο γονέα).

Την ίδια στιγμή, το ελάχιστο μέγεθος της εισόδου λεξικού θα είναι μόλις 16 bytes.

Απαντήθηκε 10/12/2018 στις 13:18
πηγή χρήστη

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