Stackoverflow εξαίρεση όταν διέρχονται BST

ψήφοι
4

Έχω εφαρμόσει ένα BST σύνδεση με βάση το (δυαδικό δένδρο αναζήτησης) σε C ++ για ένα από αποστολή μου. Έχω γράψει ολόκληρη την τάξη μου και όλα λειτουργούν καλά, αλλά αποστολή μου με ρωτάει να σχεδιάσετε τις παραμονές φορές για:

a.  A sorted list of 50000, 75000, and 100000 items
b.  A random list of 50000, 75000, and 100000 items

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

Εδώ είναι ορισμός τάξη μου:

template <class TItem>
class BinarySearchTree
{
public:
    struct BinarySearchTreeNode
    {
    public:
        TItem Data;
        BinarySearchTreeNode* LeftChild;
        BinarySearchTreeNode* RightChild;
    };

    BinarySearchTreeNode* RootNode;

    BinarySearchTree();
    ~BinarySearchTree();

    void InsertItem(TItem);

    void PrintTree();
    void PrintTree(BinarySearchTreeNode*);

    void DeleteTree();
    void DeleteTree(BinarySearchTreeNode*&);

    int CountLeaves();
    int CountLeaves(BinarySearchTreeNode*);

    int FindHeight();
    int FindHeight(BinarySearchTreeNode*);

    int SingleParents();
    int SingleParents(BinarySearchTreeNode*);

    TItem FindMin();
    TItem FindMin(BinarySearchTreeNode*);

    TItem FindMax();
    TItem FindMax(BinarySearchTreeNode*);
};

FindHeight () Εφαρμογή

template <class TItem>
int BinarySearchTree<TItem>::FindHeight()
{
    return FindHeight(RootNode);
}

template <class TItem>
int BinarySearchTree<TItem>::FindHeight(BinarySearchTreeNode* Node)
{
    if(Node == NULL)
        return 0;

    return 1 + max(FindHeight(Node->LeftChild), FindHeight(Node->RightChild));
}

CountLeaves () εφαρμογή

template <class TItem>
int BinarySearchTree<TItem>::CountLeaves()
{
    return CountLeaves(RootNode);
}

template <class TItem>
int BinarySearchTree<TItem>::CountLeaves(BinarySearchTreeNode* Node)
{
    if(Node == NULL)
        return 0;
    else if(Node->LeftChild == NULL && Node->RightChild == NULL)
        return 1;
    else
        return CountLeaves(Node->LeftChild) + CountLeaves(Node->RightChild);
}

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

Δημοσιεύθηκε 10/11/2011 στις 00:52
πηγή χρήστη
Σε άλλες γλώσσες...                            


5 απαντήσεις

ψήφοι
1

Για να μετρήσει τα φύλλα χωρίς αναδρομή, χρησιμοποιούν την έννοια ενός iterator όπως η STL χρησιμοποιεί για το RB-δέντρο υποκείμενα std::setκαι std::map... Δημιουργία begin()και end()λειτουργία για το δέντρο σας που indentifies τον διέταξε πρώτο και το τελευταίο κόμβο (σε αυτή την περίπτωση η αριστερά -το κόμβο και στη συνέχεια το δεξί πιο κόμβο). Στη συνέχεια, δημιουργήστε μια λειτουργία που ονομάζεται

BinarySearchTreeNode* increment(const BinarySearchTreeNode* current_node)

ότι για ένα δεδομένο current_node, θα επιστρέψει ένα δείκτη στον επόμενο κόμβο στο δέντρο. Λάβετε υπόψη για την εφαρμογή αυτή για το έργο, θα χρειαστείτε ένα επιπλέον parentδείκτη που σου nodeτύπο για να βοηθήσει στη διαδικασία επανάληψης.

Αλγόριθμο για increment()να δούμε κάτι σαν το παρακάτω:

  1. Ελέγξτε για να δείτε αν υπάρχει μια δεξιά παιδί με τον τρέχοντα κόμβο.
  2. Αν υπάρχει ένα δεξί παιδί, χρησιμοποιήστε μια στιγμή-βρόχο για να βρείτε το πιο αριστερό κόμβο του δικαιώματος υποδένδρο. Αυτό θα είναι το «επόμενο» κόμβο. Διαφορετικά, προχωρήστε στο βήμα # 3.
  3. Αν δεν υπάρχει δεξί παιδί στο τρέχον κόμβο, στη συνέχεια, ελέγξτε αν ο τρέχων κόμβος είναι το αριστερό παιδί του γονέα του κόμβου της.
  4. Εάν το βήμα # 3 είναι αληθές, τότε το «επόμενο» κόμβος είναι ο κόμβος γονέας, ώστε να μπορείτε να σταματήσετε σε αυτό το σημείο, αλλιώς πάμε στο επόμενο βήμα.
  5. Αν το βήμα # 3 ήταν ψευδής, τότε η τρέχουσα κόμβου είναι το δεξί παιδί του γονέα. Έτσι θα πρέπει να συνεχίσει να κινείται μέχρι την επόμενη μητρικό κόμβο χρησιμοποιώντας ένα βρόχο while, μέχρι να συναντήσετε έναν κόμβο που είναι το αριστερό παιδί του γονέα του κόμβου της. Ο γονέας του κόμβου αριστερό παιδί τότε θα είναι η «επόμενη» κόμβο, και μπορείτε να σταματήσετε.
  6. Τέλος, αν το βήμα # 5 που επιστρέφει στη ρίζα, τότε το τρέχον κόμβος είναι ο τελευταίος κόμβος στο δέντρο, και το iterator έχει φτάσει στο τέλος του δέντρου.

Τέλος, θα χρειαστεί μια bool leaf(const BinarySearchTreeNode* current_node)λειτουργία που θα δοκιμάσουν αν ένα δεδομένο κόμβο είναι ένας κόμβος φύλλο. Έτσι σε αντίθεση λειτουργία μπορεί απλά να επαναλάβει αν το δέντρο και να βρει όλους τους κόμβους φύλλα, επιστρέφοντας σε τελική καταμέτρηση μία φορά το κάνει.

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

BTW, η πολυπλοκότητα αυτής της μεθόδου είναι, δυστυχώς, θα είναι O (N) ... πουθενά κοντά τόσο ωραία όσο O (log N).

Απαντήθηκε 10/11/2011 στις 01:01
πηγή χρήστη

ψήφοι
3

Αναδρομή σε ένα δέντρο με 100.000 κόμβους δεν θα πρέπει να είναι ένα πρόβλημα αν είναι ισορροπημένη. Το βάθος ήταν μόνο ίσως 17, η οποία δεν θα χρησιμοποιούν πολύ stack στις εφαρμογές εμφανίζονται. (log2(100,000) = 16.61). Έτσι φαίνεται ότι ίσως ο κωδικός που χτίζει το δέντρο δεν το εξισορρόπηση σωστά.

Απαντήθηκε 10/11/2011 στις 01:02
πηγή χρήστη

ψήφοι
1

Μπορεί να χρειαστεί να υπολογίσετε αυτό, ενώ κάνει το ένθετο. Αποθηκεύστε τα ύψη των κόμβων, δηλαδή προσθέσετε έναν ακέραιο πεδίο, όπως το ύψος στο αντικείμενο κόμβου. Επίσης, έχει ύψος μετρητές και τα φύλλα του δέντρου. Όταν εισάγετε ένα κόμβο, εάν ο γονέας του είναι (ήταν) ένα φύλλο, η αλλαγή διαιτητή καταμέτρηση των φύλλων, αλλά αν όχι, να αυξήσει τον αριθμό των φύλλων με 1. Επίσης, το ύψος του νέου κόμβου είναι το ύψος των γονέων + 1, ως εκ τούτου, αν αυτό είναι μεγαλύτερο από το σημερινό ύψος του δέντρου και στη συνέχεια να ενημερώσετε. ένα σπίτι του, γι 'αυτό συνηθίζει να βοηθήσει με τον πραγματικό κώδικα

Απαντήθηκε 10/11/2011 στις 01:05
πηγή χρήστη

ψήφοι
2

Βρήκα αυτή τη σελίδα πολύ διαφωτιστική, επειδή μιλά για τους μηχανικούς της μετατροπής μιας λειτουργίας που χρησιμοποιεί αναδρομή σε εκείνη που χρησιμοποιεί επανάληψη.

Έχει παραδείγματα δείχνουν κώδικα, καθώς και.

Απαντήθηκε 10/11/2011 στις 01:06
πηγή χρήστη

ψήφοι
1

Ισορροπήστε το δέντρο σας περιστασιακά. Αν το δέντρο σας είναι να πάρει Stackoverflow για FindHeight (), αυτό σημαίνει ότι το δέντρο σας είναι τρόπος ισορροπημένη. Αν το δέντρο είναι ισορροπημένο θα πρέπει να έχει μόνο ένα βάθος περίπου 20 κόμβους για 100000 στοιχεία.

Ο ευκολότερος (αλλά αρκετά αργή) τρόπο επανεξισορρόπησης ασύμμετρη δυαδικό δέντρο είναι να διαθέσει μια σειρά από TItemαρκετά μεγάλη για να κρατήσει όλα τα δεδομένα στο δέντρο, εισάγετε όλα τα δεδομένα σας σε αυτό το ταξινομημένη σειρά, και να διαγράψετε όλα τα κόμβων . Στη συνέχεια, την ανοικοδόμηση το δέντρο από τη σειρά αναδρομικά. Η ρίζα είναι ο κόμβος στη μέση. root->leftείναι η μέση αριστερό μισό, root->rightείναι το μεσαίο του δεξιού μισού. Επαναλάβετε αναδρομικά. Αυτός είναι ο ευκολότερος τρόπος για να αποκαταστήσει την ισορροπία, αλλά είναι slowish και λαμβάνει προσωρινά πολλή μνήμη. Από την άλλη πλευρά, θα πρέπει να το κάνετε αυτό μόνο όταν ανιχνεύσει ότι το δέντρο είναι πολύ ισορροπημένη, (το βάθος στο ένθετο είναι πάνω από 100).

Η άλλη (καλύτερη) λύση είναι να εξισορροπήσει κατά τη διάρκεια ένθετα. Το πιο έξυπνο τρόπο για να γίνει αυτό είναι να παρακολουθείτε πόσα κόμβοι είναι κάτω από τον τρέχοντα κόμβο. Αν το δικαίωμα παιδί έχει περισσότερες από δύο φορές τόσο πολλά κόμβοι «παιδί» ως αριστερό παιδί, «περιστροφή» αριστερά. Και αντίστροφα. Υπάρχει instrcutions για το πώς να κάνετε το δέντρο περιστρέφεται σε όλο το διαδίκτυο. Το γεγονός αυτό καθιστά τα ένθετα ελαφρώς πιο αργή, αλλά τότε δεν έχετε περιστασιακή μαζικές πάγκους που δημιουργεί η πρώτη επιλογή. Από την άλλη πλευρά, θα πρέπει να ενημερώνει συνεχώς όλα τα «παιδιά» μετράει, όπως μπορείτε να κάνετε τις περιστρέφεται, η οποία δεν είναι ασήμαντο.

Απαντήθηκε 10/11/2011 στις 01:08
πηγή χρήστη

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