StackOverflow uitzondering bij het doorlopen van BST

stemmen
4

Ik heb de uitvoering van een koppeling op basis van BST (binaire zoekboom) in C ++ voor één van mijn opdracht. Ik heb mijn hele klas geschreven en alles werkt goed, maar mijn opdracht vraagt ​​me om de doorlooptijden te plotten voor:

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

Dat is prima, kan ik de nummers in te lassen, maar het vraagt me ook om de bellen FindHeight()en CountLeaves()methoden op de boom. Mijn probleem is dat ik de twee functies heeft geïmplementeerd met behulp van recursion. Aangezien ik een zo'n grote lijst van nummers Ik krijg steeds een stackoverflowuitzondering.

Hier is mijn definitie van de klasse:

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 () Uitvoering

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 () implementatie

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);
}

Ik heb geprobeerd om te bedenken hoe ik de twee methoden zonder recursie kan implementeren, maar ik ben helemaal stumped. Iemand enig idee?

De vraag is gesteld op 10/11/2011 om 00:52
bron van user
In andere talen...                            


5 antwoorden

stemmen
1

Met het oog op de bladeren tellen zonder recursie, gebruik van het concept van een iterator zoals de STL gebruikt voor de RB-tree die ten grondslag liggen std::seten std::map... Maak een begin()en end()functie voor u boom die de bestelde eerste en laatste knooppunt identificeert (in dit geval de linker -De meeste knooppunt en de meest rechtse knooppunt). Maak vervolgens een functie genaamd

BinarySearchTreeNode* increment(const BinarySearchTreeNode* current_node)

dat voor een gegeven current_node, zal een pointer terug te gaan naar het volgende knooppunt in de boom. Houd in gedachten voor deze implementatie aan het werk, geeft je een extra nodig parentpointer in uw nodetype om te helpen bij het iteratie proces.

Uw algoritme increment()zou iets als volgt uitzien:

  1. Controleer om te zien of er een recht-kind om het huidige knooppunt.
  2. Als er een recht-kind, gebruik maken van een while-lus naar de meest linkse knooppunt van die rechter deelboom vinden. Dit zal de "volgende" node. Anders gaat u naar stap # 3.
  3. Als er geen recht-kind op de huidige node, kijk dan om te zien of het huidige knooppunt is de linker kind van de bovenliggende node.
  4. Als stap 3 waar is, dan is de "next" knooppunt is het bovenliggende knooppunt, zodat u kunt stoppen op dit punt, anders wordt de volgende stap te gaan.
  5. Als de stap # 3 fout was, dan is de actuele node de rechter kind van de ouder. Zo moet u op de hoogte blijven bewegen naar de volgende bovenliggende knooppunt met behulp van een while lus totdat je tegenkomt een knooppunt dat is een linker-kind van de bovenliggende node. De ouder van deze links-kind-knooppunt zal dan de "volgende" knooppunt, en je kunt stoppen.
  6. Tot slot, als stap # 5 keert u terug naar de wortel, dan is de huidige knooppunt is de laatste knoop in de boom, en de iterator heeft het einde van de boom bereikt.

Tot slot vindt u een nodig bool leaf(const BinarySearchTreeNode* current_node)functie die zal testen of een gegeven knooppunt een blad node. Zo kunt teller functie kan gewoon herhalen hoewel de boom en vind alle het blad nodes, het terugsturen van een definitieve telling zodra het klaar is.

Wilt u de maximale diepte van een onevenwichtige boom zonder recursie te meten, zult u, in uw boom insert()functie wilt bijhouden van de diepte die een knooppunt is ingevoegd te houden. Dit kan eenvoudig een variabele in zijn nodesoort, dat wordt ingesteld wanneer de node in de boom is geplaatst. U kunt dan doorlopen de drie, en vind de maximale diepte van een blad-node.

BTW, is de complexiteit van deze methode helaas gaat O (N) zijn ... nergens dichtbij zo mooi als O (log N).

antwoordde op 10/11/2011 om 01:01
bron van user

stemmen
3

Recursie op een boom met 100.000 nodes moet geen probleem zijn als het evenwicht wordt gebracht. De diepte zou slechts misschien 17, die niet veel stapel in de getoonde uitvoeringen zou gebruiken. (log2(100,000) = 16.61). Dus het lijkt erop dat misschien de code dat de boom is het bouwen is het niet de juiste afweging.

antwoordde op 10/11/2011 om 01:02
bron van user

stemmen
1

Mag je nodig hebt om dit te berekenen terwijl het doen van het inzetstuk. Bewaar de hoogten knooppunten, namelijk voeg een integerveld zoals lengte van de Knoopobject. Ook hebben tellers hoogte en bladeren van de boom. Wanneer u een knooppunt in te voegen, als de ouder is (was) een blad, het blad telling doesnt verandering, maar zo niet, verhoog blad telling door 1. Ook de hoogte van het nieuwe knooppunt ouders hoogte + 1, dus als dat groter is dan de huidige hoogte van de boom, werkt het dan. Het is een huiswerk, dus ik zal niet helpen met de werkelijke code

antwoordde op 10/11/2011 om 01:05
bron van user

stemmen
2

Ik vond deze pagina zeer verhelderend, omdat het gaat over de mechanica van het omzetten van een functie die recursie gebruikt om een die iteratie gebruikt.

Zij voorbeelden tonen code ook.

antwoordde op 10/11/2011 om 01:06
bron van user

stemmen
1

Balance uw boom af en toe. Als uw boom krijgt Gebruiker op FindHeight (), dat betekent dat uw boom is weg onevenwichtig. Als de boom evenwichtig moet slechts een diepte van ongeveer 20 knopen voor 100000 elementen.

De eenvoudigste (maar vrij traag) manier van het herstel van het evenwicht uit balans binaire boom is om een reeks toe te wijzen TItemgroot genoeg om alle gegevens in de boom te houden, plaatst u al uw gegevens erin in gesorteerde volgorde, en verwijder alle van de knooppunten . Weer op te bouwen dan de boom uit de array recursief. De wortel is het knooppunt in het midden. root->leftligt verzonken in de linkerhelft, root->rightis het midden van de rechterhelft. Herhaal recursief. Dit is de makkelijkste manier om in evenwicht te brengen, maar het is slowish en neemt veel geheugen tijdelijk. Aan de andere kant heb je dit alleen te doen als je ontdekt dat de boom is zeer onevenwichtig, (diepte op insert is meer dan 100).

De andere (beter) optie is om in evenwicht te brengen tijdens de inserts. De meest intuïtieve manier om dit te doen is om bij te houden hoeveel nodes zijn onder de huidige knooppunt te houden. Als het juiste kind heeft meer dan twee keer zo veel "kind" nodes zoals het linker kind, "draaien" links. En vice versa. Er is instrcutions over hoe dat te doen boom roteert over het hele internet. Dit maakt inserts iets langzamer, maar dan hoef je niet af en toe een massale kraampjes dat de eerste optie maakt. Aan de andere kant, je moet voortdurend actualiseren alle "kinderen" telt als je het draait niet, dat is niet triviaal.

antwoordde op 10/11/2011 om 01:08
bron van user

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