Bináris fa Rotation

szavazat
3

Dolgozom végrehajtása AVL Keresés fa. Eddig elkészült kódoló részének és elkezdtem tesztelés a hibákat. Rájöttem, hogy az én node forgatás módszerek poloska és az isten szerelmére nem értem mi a probléma.

Az algoritmus működik, ahogy kellene papíron, de amikor végre egy gép jól ... szivárog facsomópontok.

Ez az a módszer, hogy forgatni egy csomópont balra: http://pastebin.com/mPHj29Af

bool avl_search_tree::avl_tree_node::rotate_left()
{
    if (_right_child != NULL) {
        avl_tree_node *new_root = _right_child;
 
        if (_parent != NULL) {
            if (_parent->_left_child == this) {
                _parent->_left_child = new_root;
            } else {
                _parent->_right_child = new_root;
            }
        }
 
        new_root->_parent = _parent;
        _parent = new_root;
 
        _right_child = new_root->_left_child;
        new_root->_left_child = this;
 
        if (_right_child != NULL) {
            _right_child->_parent = this;
        }
 
        //update heights
        update_height();
        new_root->update_height();
 
        return true;
    }
 
    return false;
}

Az én behelyezés módszer azt nyilatkozta az AVL beszabályozó és ehelyett csak próbálok forgatni az újonnan beillesztett csomópontot a bal oldalon. Az eredmény behelyezésére egész emelkedő sorrendben: fám csak azokat a kezdeti gyökér (első csomópont helyezve), és az összes többi csomópont kiszivárgott.

Bármilyen segítséget a probléma azonosítása nagyra értékelik kezdek megőrülni.

A rekord: ha nem használ semmilyen forgatások a fa nem szivárog csomópontok és úgy működik, mint egy normális kiegyensúlyozott bináris keresési fa (behelyezhető és keresés).

Edit: Mivel AJG85 megjegyzését adom hozzá a megfigyelések:

Tettem hozzá printf „ellenőrzés” a destruktor módszer avl_search_tree :: avl_tree_node hogy kiírja a kulcs értékét (esetemben 32 bites egészek), mielőtt tisztítási és a betét módszere avl_search_tree hogy kiírja a kulcs csak ki.

Ezután a program BelépésiPont hozzárendelhetek egy avl_search_tree a halom, és adjunk hozzá kulcs szolgál emelkedő sorrendben, majd törli.

Az AVL kiegyensúlyozó engedélyezve kapom a következő kimenetet a terminál:

bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1

Ami azt jelenti, thatall betoldások sikeresek voltak, de csak a root törölték.

Az AVL Kiegyensúlyozó megjegyzésbe úgy működik, mint egy normál bináris kereső fába. A terminál kimenet:

bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1
avl_search_tree::avl_tree_node::~avl_tree_node() : 2
avl_search_tree::avl_tree_node::~avl_tree_node() : 3
avl_search_tree::avl_tree_node::~avl_tree_node() : 4
avl_search_tree::avl_tree_node::~avl_tree_node() : 5
avl_search_tree::avl_tree_node::~avl_tree_node() : 6
avl_search_tree::avl_tree_node::~avl_tree_node() : 7
avl_search_tree::avl_tree_node::~avl_tree_node() : 8

Ami azt jelenti, hogy minden tökéletesen tisztítani.

Most ... hogy én arra a következtetésre jutottam, hogy a forgatás módszerek a kérdések? Az hozzászólt AVL kiegyensúlyozó szubrutin tettem hozzá egy sort, hogy forog minden újonnan bevezetett csomópont balra. Az eredmény? Ugyanaz, mint ha az AVL kiegyensúlyozó szubrutin engedélyezve.

És kapcsolatos update_height () metódus, ez nem változtat a fa szerkezet bármilyen módon.

Remélem, ez tisztázza.

Szerkesztés 2:

Tisztázni néhány több dolgot, ő az, hogy a avl_tree_node destruktor végre:

avl_search_tree::avl_tree_node::~avl_tree_node()
{
    printf(%s : %d\n, __PRETTY_FUNCTION__, *_key);

    if (_left_child != NULL) {
        delete _left_child;
    }

    if (_right_child != NULL) {
        delete _right_child;
    }

    if (_key != NULL) {
        delete _key;
    }
}

_left_child és _right_child mutató pointer avl_tree_node tárgyakat osztottak ki a kupac.

Edit 3:

Hála AGJ85 a 2. megjegyzést találtam a problémát. Az én forgatás módszerek Elfelejtettem, hogy valóban meg kell frissíteni a fa gyökér mutatót az új gyökér, amikor a gyökér tolódott.

Alapvetően a fa gyökere mindig mutat az első beillesztett csomópont és frissítése nélkül a mutató, ha szükséges, a forgatás módszerek is szivárog az új fa gyökere, amely ténylegesen konfigurálva van. :)

Köszönöm AGJ85!

A kérdést 02/08/2011 18:19
a forrás felhasználó
Más nyelveken...                            


3 válasz

szavazat
2

EDIT - A fenébe - Nem látja, hogy a probléma már megoldódott (válasz kérdéses). Mégis, talán van néhány nem választ tippeket ebben érdemes megmentése.

Nem néztem alaposan, de azt hiszed, rosszat ebben a sorban ...

_right_child = new_root->_left_child;

és hogy a probléma az, hogy lehet, hogy már felülírta new_root->_left_childa sorban ...

_parent->_left_child = new_root;

Azt hiszem, meg kell tennie, hogy az elején, van egy blokk lokális definíciók, mint ...

avl_tree_node *orig_parent      = _parent;
avl_tree_node *orig_this        = this;
avl_tree_node *orig_left_child  = _left_child;
avl_tree_node *orig_right_child = _right_child;

Ezután a orig_helyi változókat, mivel a források későbbi feladatok. Ez ment egy bizonyos mennyiségű aggódni adatforgalom a különböző mutatók a forgás közben. Az optimalizáló kell megszabadulni minden felesleges munkát érdemes aggódni ezen, és nincs sok, hogy egyébként.

Egy pár extra pontot ...

Először is, a C ++ (és C) szabványok tartalék azonosítók vezető aláhúzás, és dupla-aláhúzás. Azt állítják, hogy lehet kapni meglepetést kölcsönhatások standard és fordító által szállított könyvtárakat, ha nem tartják tiszteletben, hogy - azt hiszem, hogy volna, hogy makro-rokon az elem azonosítók, mégis. Záró aláhúzásjelek OK - Én inkább használni őket tartalmazzák őrök.

A közös egyezmény tagváltozóival, hogy adjunk egy vezető mvagy m_. Még gyakoribb, valószínűleg nem, hogy bármilyen különleges elő- vagy utótagot egyáltalán.

Másodszor, meg lehet (vagy nem), könnyebben tudnak végrehajtani AVL fák, amelyek nem rendelkeznek a szülő kapcsolat alatt a csomópontokat. Én nem hajtották végre AVL fák még magam, de én végre piros-fekete fák egyszer. Számos algoritmus kell tartalmaznia rekurzív keresés, mint az első lépés - nem lehet csak úgy csinálni a normál keresési emlékezik a talált csomópont, de elveti az útvonalon le a csomópontot. Azonban rekurzív megvalósítása nem túl rossz, és van kevesebb mutatókat kell bűvészkedni.

Végül általános tip - megpróbálja „szárazon futás” egy olyan algoritmus, mint ez könnyen utazás téged, ha nem feltétlenül a munka révén lépésről lépésre, és ellenőrizze az összes információforrást, amelyek relevánsak (volna már módosított ez?) Itt minden lépés. Ez nagyon könnyű bejutni a szokást, hogy kihagy néhány részletet a sebesség. Egy hasznos gép segített száraz távon futtatja a kódot, lépésről-lépésre egy debugger, és látni, ha az eredmények minden lépésben ért egyet a papír szárazon futás.

EDIT - még egy megjegyzés - Én nem nevezném ezt a tip, mert nem vagyok biztos ebben az összefüggésben. Általában végre adatstruktúra csomópontok egyszerű struktúrákat - nincs adat rejtőzik, kevés, ha valamely tagja funkciókat. A legtöbb kódot külön tartják az adatstruktúra, gyakran egy „eszköz” osztályú. Tudom, hogy ez megtöri a régi „alakja von maga” OOP elvileg, de IMO ez jobban működik a gyakorlatban.

Válaszolt 02/08/2011 20:34
a forrás felhasználó

szavazat
3

Hála AGJ85 a 2. megjegyzést találtam a problémát. Az én forgatás módszerek Elfelejtettem, hogy valóban meg kell frissíteni a fa gyökér mutatót az új gyökér, amikor a gyökér tolódott.

Alapvetően a fa gyökere mindig mutat az első beillesztett csomópont és frissítése nélkül a mutató, ha szükséges, a forgatás módszerek is szivárog az új fa gyökere, amely ténylegesen konfigurálva van. :)

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

szavazat
1

Látom megtaláltad a hibát, amit keresett a kódban. (Ahogy mondod, hogy nem frissíti a gyökérben mutatót az új gyökér, amikor a gyökér változott. Ez egy közös paradigma lista és fa Insert / Delete módszereket, hogy visszatérjen egy pointert vezetője listából vagy gyökér fa, és ha emlékszel arra a paradigma nem fogja a hibát.)

Magasabb szinten nézve, a technika, amit használnak, hogy elkerülhető legyen az AVL fa vagy piros-fekete fa kód e helyett egy AA fa , amely hasonló teljesítményt nekik, O (n) tér és az O (log n) idő Insert, Delete, és keresés. Azonban AA fák lényegesen egyszerűbb kódot.

Válaszolt 04/08/2011 16:55
a forrás felhasználó

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