İkili Ağacı Rotasyon

oy
3

Bir AVL Arama ağacını uygulama üzerinde çalışıyorum. Şimdiye kadar kodlama bölümünü bitirdim ve ben hatalar için onu test başladık. Benim düğüm rotasyon yöntemleri dinlenmişti öğrendim ve Allah aşkına ben sorunun ne olduğunu anlayamıyorum.

Algoritma bu kağıt üzerinde gerektiği ancak bir makinede çalıştırıldığında iyi ... ağaç düğümlerini sızdırıyor olarak çalışmaktadır.

Bu işlem, soldaki bir düğüm döndürmek için kullanılan yöntem şu şekildedir: 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;
}

Benim yerleştirme yönteminde Rolü dengeleme AVL yorumladı ve bunun yerine sadece sola, yeni eklenen düğüm döndürmek çalışıyorum. Benim ağaç sadece ilk kök (takılı birinci düğüm) ve diğer tüm düğümler sızdırılmış içerir: küçükten büyüğe tamsayılar eklemek için sonucu.

Ben delirmek başlıyorum olarak sorunu tespit herhangi bir yardım büyük beğeni toplamaktadır.

Kayıt için: Ben herhangi bir rotasyonları kullanan yoksa ağaç düğümlerini sızıntı olmaz ve onu (yerleştirme ve arama için) normal dengesiz ikili arama ağacı olarak çalışmaktadır.

Düzenleme: AJG85 yorumuna nedeniyle ben gözlemlerini ekleyeceğiz:

Sadece sokulan anahtar yazdırır avl_search_tree insert yöntemine, temizleme önce (benim durumumda 32 bitlik tamsayılar olarak) anahtar değeri yazdırmak ve edecektir avl_search_tree :: avl_tree_node yıkıcı yöntemine Printf çekleri 'eklendi.

Ardından programın GirişNoktası ben öbek bir avl_search_tree tahsis ve artan düzende kendisine anahtarları ekleyebilir ve ardından silin.

AVL Dengeleme etkinken ben terminalde şu çıktıyı almak:

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

Hangi eklemeler başarılı ama sadece kök silindi thatall gelir.

AVL dışarı yorumladı Dengeleme ile normal bir ikili arama ağacı gibi çalışır. Terminal çıktısı:

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

Hangi herşey düzgün temizlenir anlamına gelir.

Şimdi ... nasıl rotasyon yöntemleri konular olduğunu sonucuna geldi? yorumunu AVL dengeleme alt yordam altında daha sola her yeni eklenen düğüm döner bir çizgi ilave edildi. Sonuç? AVL Dengeleme altprogram etkin sanki aynı.

Ve update_height () yöntemine ilişkin, Herhangi bir şekilde ağacın yapısını değiştirmez.

Bu olayı aydınlatmak umuyoruz.

Düzenleme 2:

Biraz daha şeyleri netleştirmek için, onun avl_tree_node yıkıcı nasıl uygulandığını geçerli:

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 ve _right_child yığın tahsis nesneleri avl_tree_node göstericisidir.

Düzenleme 3:

AGJ85 2'nci açıklama sayesinde Sorunu buldum. Benim döndürme yöntemlerinde Ben aslında kök kaydırıldı her yeni köküne ağacın kök işaretçisi güncellemek zorunda olduğunu unuttum.

Temelde ağacın kökü her zaman ilk sokulan düğüme ve işaretçi gerektiğinde, benim döndürme yöntemleri aslında doğru yapılandırılmış yeni ağacın kökü kaçırır ama güncellemeden işaret ediyordu. :)

Size AGJ85 ederiz!

Oluştur 02/08/2011 saat 18:19
kaynak kullanıcı
Diğer dillerde...                            


3 cevaplar

oy
2

DÜZENLEME - Aynen - Sorunun zaten çözüldüğünü (söz konusu cevap) görmedim. Yine de, belki bu değer kurtarılma olmayan bazı cevap ipuçları var.

İyice Kontrol etmedim ama bu satırında yanlış gittiğini sanıyorsun ...

_right_child = new_root->_left_child;

ve problem zaten üzerine olabileceğini olduğu new_root->_left_childdoğrultusunda ...

_parent->_left_child = new_root;

Ne Bence yapmanız gereken başlangıcında gibi yerel tanımların bir blok var, bir ...

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;

Sonra kullanmak orig_daha sonraki ödevler için kaynak olarak yerel değişkenler. Bu verilerin endişesi belli bir miktar dönme sırasında çeşitli işaretçiler akar kaydeder. Optimiser bunda endişelenmeye değer herhangi gereksiz işin kurtulmak gerektiğini ve bu oldu Neyse çok yoktur.

Ekstra puan Birkaç ...

İlk olarak, C ++ (ve C) gelen çizgi ile ve çift alt çizgi ile standartları rezerv tanımlayıcıları. O buna saygı yoksa standart ve derleyici tarafından sağlanan kitaplıkları ile sürpriz etkileşimleri alabilirsiniz ileri sürülüyor - Ama bunun üye tanımlayıcılar için makro ilgili olmak gerekiyor demek. Firar alt çizgi Tamam - Ben korumaları dahil onları kullanma eğilimindedir.

Üye değişkenler için ortak bir kongre öncü eklemektir mveya m_. Hatta daha yaygın, muhtemelen, hiç bir özel önek veya sonek sahip değildir.

İkincisi, (veya olmayabilir) daha kolay düğümler saklanan ebeveyn bağlantılar olmadığından AVL ağaçları uygulamaya bulabilirsiniz. Ben AVL ağaçları henüz kendimi uygulanmadı, ama ben bir kez kırmızı-siyah ağaçları uygulamak yaptı. algoritmalar bir dizi ilk adım olarak bir özyinelemeli arama eklemeniz gerekir - sadece bulundu düğüm hatırlar ama bu düğüme aşağı rotayı atar standart bir arama yapamaz. Ancak, özyinelemeli uygulama çok kötü değil ve hokkabazlık yapmaya daha az işaretçiler var.

Son olarak, genel bir ipucu - Eğer sürece "kuru çalıştırma" Böyle bir algoritma kolayca çelme edebilir çalışırken kesinlikle içinden iş adım adım ve alakalı tüm bilgi kaynaklarını kontrol (Zaten bu değiştirdiniz?) De her adım. Bu hız için bazı ayrıntıları atlama alışkanlık haline almak çok kolaydır. Yararlı bir makine yardımıyla kuru çalıştırma bir hata ayıklayıcıda kodunu adım adım çalıştırın ve her adımda sonuç Kağıdın kuru vadede kabul ediyorsanız görmektir.

DÜZENLEME - bir daha not - Ben bu bağlamda emin değilim çünkü bu bir ipucu aramayacak. Hiçbir veri gizleme, birkaç herhangi bir üyesi fonksiyonları eğer - Ben genellikle basit yapılar ile veri yapısı düğümleri uygulamak. Kodun Çoğu zaman bir "aracı" sınıfında, veri yapısından ayrı tutulur. Bu "şekil kendisini çizer" eski cepten prensibini kırar biliyorum ama IMO uygulamada daha iyi çalışır.

Cevap 02/08/2011 saat 20:34
kaynak kullanıcı

oy
3

AGJ85 2'nci açıklama sayesinde Sorunu buldum. Benim döndürme yöntemlerinde Ben aslında kök kaydırıldı her yeni köküne ağacın kök işaretçisi güncellemek zorunda olduğunu unuttum.

Temelde ağacın kökü her zaman ilk sokulan düğüme ve işaretçi gerektiğinde, benim döndürme yöntemleri aslında doğru yapılandırılmış yeni ağacın kökü kaçırır ama güncellemeden işaret ediyordu. :)

Cevap 03/08/2011 saat 10:03
kaynak kullanıcı

oy
1

Ben size kodunda aradığını hata bulduk görüyoruz. Dediğiniz gibi kök değişti (yeni köke ağaç kökü işaretçisi güncellenmesi değildi. O listeye ve ağaç Ekle için ortak paradigma var / liste veya ağacın köküne başkanına bir işaretçi dönmek için yöntemler silin ve eğer Eğer paradigma tekrar hata yapmaz unutmayın.)

Görüş yüksek bir seviyede, teknik Ben sorunlarını önlemek üzere kullandım AVL Ağacı veya Kırmızı-Siyah Ağaç kodu yerine kullanmaktır AA Ağacı O (n) alan ve O (günlüğünü kullanarak, onlara benzer bir performansa sahiptir, Ekle için n) zamanda, Sil ve arama yapın. Ancak, AA ağaçları koduna önemli ölçüde daha basittir.

Cevap 04/08/2011 saat 16:55
kaynak kullanıcı

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