StackOverflow kivételt áthaladó BST

szavazat
4

Van végre egy link-alapú BST (bináris keresési fa) a C ++ az egyik feladat. Írtam az egész osztály, és minden jól működik, de a feladat kér, hogy a telek futási idők:

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

Ez rendben van, azt írhatjuk be a számokat, de azt is kéri, hogy hívjam a FindHeight()és CountLeaves()módszerek a fán. A problémám az, hogy én már végre a két funkció használatával recursion. Mivel van egy ilyen nagy számok listáját kapok kapok egy stackoverflowkivétel.

Itt a osztály definíció:

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 () végrehajtása

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 () végrehajtása

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

Próbáltam arra gondolni, hogyan lehet végrehajtani a két módszer nem rekurzív, de én teljesen zavarba. Bárki bármilyen ötleted?

A kérdést 10/11/2011 00:52
a forrás felhasználó
Más nyelveken...                            


5 válasz

szavazat
1

Annak érdekében, hogy számít a levelek nélkül rekurzió fogalmát használják olyan iterátornál mint az STL használ az RB-tree szolgáló std::setés std::map... létrehozása begin()és end()funkció az Ön számára, fa, indentifies a megrendelt első és az utolsó csomópont (ebben az esetben a bal oldali -A legtöbb csomópontot, majd a jobb oldali csomópont). Ezután hozzon létre olyan függvény

BinarySearchTreeNode* increment(const BinarySearchTreeNode* current_node)

hogy egy adott current_node, vissza fog térni egy mutatót a következő csomópontot a fán. Tartsuk szem előtt, erre a végrehajtás munka, akkor szükség van egy extra parentmutató a nodetípus, hogy segítse az iterációs folyamat.

Az algoritmus increment()a következőképpen néz ki a következőket:

  1. Nézze meg, hogy van egy jobb gyermek az aktuális csomópont.
  2. Ha van egy jobb gyermek használjon míg hurok, hogy megtalálják a bal szélső csomópontja, hogy jobb részfa. Ez lesz a „következő” csomópontot. Ellenkező esetben folytassa a # 3.
  3. Ha nincs jobb gyermek az aktuális csomópont, akkor nézze meg, ha az aktuális elem a bal-gyermek a szülő csomópont.
  4. Ha lépésben # 3 igaz, akkor a „következő” csomópont a szülő csomópont, így megáll ezen a ponton, különben menj a következő lépésre.
  5. Ha a 3. lépés szerint hamis volt, akkor az aktuális elem a jobb gyermek a szülő. Így meg kell mozogni felfelé a következő szülő csomópontot while, amíg meg nem találkoznak olyan csomópont, amely egy bal-gyermek a szülő csomópont. A szülő ennek bal gyermek csomópont ekkor a „következő” csomópont, és akkor megáll.
  6. Végül, ha lépést # 5 visszatér a gyökér, akkor az aktuális csomópont az utolsó csúcs a fában, és a bejáró a végére ért a fa.

Végül szüksége lesz egy bool leaf(const BinarySearchTreeNode* current_node)függvény, amely próbára, hogy egy adott csomópont levél csomópont. Így számláló funkció egyszerűen hajtogat, bár a fát, és megtalálja a levél csomópontok, visszatérve a végső szám, ha ez történik.

Ha azt szeretnénk, hogy az intézkedés a maximális mélysége kiegyensúlyozatlan fa nélkül rekurzió, akkor, a fa insert()funkció kell nyomon követni a mélység, hogy egy csomópontnak építünk be. Ez lehet egyszerűen egy változó a nodetípus van beállítva, ha a csomópont van helyezve a fa. Ezután végighaladni a három, és keresse meg a maximális mélysége levél csomópont.

BTW, összetettsége ezt a módszert sajnos lesz O (N) ... közel sem olyan szép, mint O (log N).

Válaszolt 10/11/2011 01:01
a forrás felhasználó

szavazat
3

A rekurzió egy fa 100000 csomópont nem lehet probléma, ha kiegyensúlyozott. A mélység csak akkor lenne talán 17, ami nem használ nagyon verem a megvalósítások látható. (log2(100,000) = 16.61). Tehát úgy tűnik, hogy talán a kódot, amely épít a fát nem kiegyensúlyozó helyesen.

Válaszolt 10/11/2011 01:02
a forrás felhasználó

szavazat
1

Lehet meg kell kiszámítani ezt mindeközben a betét. Tárolja a magasból csomópontok, azaz adjunk egy egész területén, mint a magasság a Node objektumot. Is számlálók magasság és a levelek a fa. Ha behelyez egy csomópontot, ha a szülő (volt) egy levél, a levél száma doesnt változás, de ha nem, akkor növelni levél számlálót 1 Szintén a magassága az új csomópontot szülő magasság + 1, tehát ha ez nagyobb, mint a jelenlegi fa magasságát, majd frissíteni. Ez egy házi, tehát én szokás segít a tényleges kódot

Válaszolt 10/11/2011 01:05
a forrás felhasználó

szavazat
2

Találtam ezt az oldalt nagyon tanulságos, mert beszél a mechanika konvertáló funkció, amely a rekurzió egy használó iteráció.

Ez példa mutatja kódot is.

Válaszolt 10/11/2011 01:06
a forrás felhasználó

szavazat
1

Egyensúlyt a fa néha. Ha a fa egyre StackOverflow on FindHeight (), ami azt jelenti, hogy a fa utat kiegyensúlyozatlan. Ha a fa kiegyensúlyozott ez csak mélysége mintegy 20 csomópontok 100000 elemekkel.

A legegyszerűbb (de nagyon lassú) módon újra egyensúlyba kiegyensúlyozatlan bináris fa kiosztani egy sor TItemnagy ahhoz, hogy tartsa az összes adatot a fán, helyezze az összes adatot bele rendezett sorrendben, és törölje az összes csomóponton . Majd újjáépíteni a fa tömb rekurzív. A gyökér a csomópont közepén. root->lefta közepén a bal fele, root->righta középső a jobb felét. Ismételjük meg rekurzívan. Ez a legegyszerűbb módja annak, hogy újra egyensúlyba hozni, de ez slowish és tart sok memóriát átmenetileg. Másrészt, ha csak ezt, ha azt észleli, hogy a fa nagyon kiegyensúlyozatlan, (mélysége betét több, mint 100).

A másik (jobb) megoldás az, hogy egyensúlyt során betétekkel. A leginkább intuitív módon, hogy ennek az, hogy nyomon követheti, hogy hány csomópont alatt az aktuális csomópont. Ha a jobb oldali gyermek több, mint kétszer annyi a „gyermek” csomópontok, mint a bal gyerek „Forgatás” maradt. És fordítva. Van instrcutions hogyan kell csinálni fa forog az egész internet. Ez teszi betétek valamivel lassabb, de akkor nem kell alkalmi hatalmas standokon, hogy az első lehetőség teremt. Másrészt, meg kell, hogy folyamatosan frissítse az összes „gyermek” számít, mint te az forog, ami nem triviális.

Válaszolt 10/11/2011 01:08
a forrás felhasználó

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