İkili ağacın bir arama ağacı olup olmadığını test etme ve tüm dalları sayma algoritması


10

İkili bir ağaç bir ikili arama ağacı olup olmadığını görmek için özyinelemeli bir algoritma oluşturmak ve aynı zamanda varsayılan bir sayma değişkeni ile kaç tam dalları var (hem sol hem de sağ çocuk düğümleri ile bir üst düğüm) saymak gerekir. Bu benim veri yapıları sınıfım için bir ödev.

Şimdiye kadar var

void BST(tree T) {
   if (T == null) return
   if ( T.left and T.right) {
      if (T.left.data < T.data or T.right.data > T.data) {
        count = count + 1
        BST(T.left)
        BST(T.right)
      }
   }
}

Ama bunu gerçekten anlayamıyorum. Bu algoritma sorunu çözmeyeceğini biliyorum çünkü ikinci deyim doğru değilse sayı sıfır olacaktır.

Birisi bana bu konuda yardımcı olabilir mi?


Karşılaştırma operatörü <düğümlerde nasıl tanımlanır?
Joe

İkili bir arama ağacı olmasa bile sayıyı hesaplamak ister misiniz?
Joe

1
Algoritmanızın trueveya gibi bir şey döndürmesi gerekiyor falsemu?
Joe

2
Belki önce iki ayrı fonksiyon tanımlamaya çalışmalısınız: Biri bir BST olup olmadığını kontrol etmek için ve diğeri tüm dalları saymak için. Bu daha yönetilebilir olmalı.
sepp2k

1
@OghmaOsiris Söylediğini hayal ediyorum çünkü soru temelde "İşte kodum, nasıl çalıştırabilirim?". Kod sözde (ish) çeşitliliğinden olmasaydı, kesinlikle bir SO sorusu olurdu.
sepp2k

Yanıtlar:


10

Diğerlerinin zaten yorumlarda belirttiği gibi, burada gerçekten alakasız iki fonksiyonunuz var: ağacın bir arama ağacı olup olmadığını test etmek ve tüm dalları saymak. Ödev özellikle gerektirmedikçe, iki ayrı işlev yazardım.

Bakalım ilk önce tüm dalları sayıyoruz. Bu, hem sol çocuğu hem de sağ çocuğu olan düğümleri saymak anlamına gelir. Sonra sayacı (artırmaz gerekir count = count + 1) her iki T.leftve T.rightboş olmayan (yoksa T.left.datave T.right.data: veriler bu görev için önemli değil).

if (T.left and T.right) {
    count = count + 1

Ayrıca, sağ alt ağaç boş olsa bile sol alt ağacı keşfetmeniz ve sol alt ağaç boş olsa bile sağ alt ağacı keşfetmeniz gerekir. Yani yinelemeli çağrıları nereye koyduğunuzu izleyin.

Ağacın bir arama ağacı olup olmadığını test etmek için veri değerlerini kontrol etmeniz gerekir. Zaten doğru karşılaştırmaya yakın bir şeyiniz var; tam olarak doğru değil. Çeşitli şekillerde (çok büyük değil, 2 ila 5 düğüm) birkaç örnek ağaç yazın ve ne olduğunu görmek için algoritmanızı çalıştırın.

Geçerlilik kontrolünün sonucunu koymak için hala bir yer bulmanız gerekiyor. Tekrarlayın, yinelemeli çağrıları nereye koyduğunuzu izleyin (sadece bu kısmı yaparsanız, birkaç çözüm vardır, ancak bu aşamada sadece bir tane görürseniz endişelenmeyin).

Son olarak, her iki işlevi de ayrı ayrı yazmayı başardıktan ve birkaç örnek üzerinde test ettikten sonra, dikkatlice bir araya getirin (ödev tarafından isteniyorsa).


teşekkürler, soruyu tekrar okudum ve ayrı yöntemler olması gerekiyordu.
OghmaOsiris

7

Böyle şeylerde, geriye doğru düşünmek genellikle daha kolaydır, bu yüzden önce neye ihtiyacınız olduğunu düşünün. Açıklamanızdan, bunları listeleyelim:

  • özyineleme
  • Geçerlilik
  • Komple düğüm sayısı

Tamam, bu oldukça kısa bir liste, bu yönetilebilir olmalı. Boş bir yöntemle başlayalım ve ne olması gerektiğinin açıklamasını ekleyeceğim.

valid_bst () {
}

Şimdi geçerlilik. Geçerliliği nasıl kontrol edersiniz? Sohbette bir ağacın geçerli olduğunu söylediniz "eğer ... soldaki tüm çocuklar ebeveynlerinden küçük ve sağ çocuklar ebeveynlerinden büyükse." Eminim siz de eşitliğe izin verdiniz. Bu olurdu t.left.value <= t.value <= t.right.value.

valid_bst () {
    This node is valid if t.left.value <= t.value <= t.right.value
}

Peki ya çocuklardan biri eksikse? Söylediklerinizden biri, eğer biri eksikse (ya da her ikisi de), düğümün hala geçerli olduğunu bildiğinize inanıyorum. Bunu biraz yeniden yapılandırarak ekleyelim:

valid_bst () {
    This node is valid to the left if 
        there is no left child or 
        it is no greater than the current node.
    This node is valid to the right if 
        there is no right child or 
        it is no less than the current node.
    This node is valid overall if it is valid to the left and right.
}

Tamam, şimdi bu düğümün geçerli olup olmadığını biliyoruz. Tüm ağacın geçerli olup olmadığını nasıl kontrol edebiliriz? Bir dizide değil, bu yüzden muhtemelen doğrusal olarak döngü yapmak istemiyoruz / istemiyoruz. Ödeviniz cevabı veriyor: özyineleme. Fakat özyineleme kullanarak nasıl bir cevap biriktirebiliriz? Bu düğümün geçerli olup olmadığı ve sol ve sağ düğümlerin geçerli olup olmadığını soran çağrıların sonucu olarak üç bilgiye erişebiliriz. Açıkçası, ağaç sadece bu üçünün hepsi doğru olduğunda geçerlidir.

valid_bst () {
    This node is valid to the left if 
        there is no left child or 
        it is no greater than the current node.
    This node is valid to the right if 
        there is no right child or 
        it is no less than the current node.
    This node is valid overall if it is valid to the left and right.
    Is the left child valid?
    Is the right child valid?
    This tree is only valid if this node and both its children are.
}

Eğer dikkat ediyorsanız, bu bize fonksiyonumuzun neye geri dönmesi gerektiğini bile söyler.

Şimdi saymayı nasıl entegre ederiz? Neyin önemli olduğunu söylüyorsunuz ("hem sol hem de sağ alt düğümleri olan bir üst düğüm") ve bunun gerçek koda çevrilmesi zor olmamalı. Bu koşulun karşılanıp karşılanmadığını kontrol edin ve sayacı uygun şekilde artırın. Sadece bunun her doğru olduğunda ulaşılacağı bir yerde olması gerektiğini unutmayın.

Ve tabii ki özyineleme durdurma koşulu ve null olup olmadığını denetleme gibi bazı ayrıntıları dışarıda bıraktım.


6

Yukarıdaki üç yorumum, kodunuzla ilgili sorunlara ilişkin üç ipucudur.

  1. Bir karşılaştırma operatörünün düğüm veri türünü nasıl ele alması gerektiğini özel olarak tanımlamadıysanız, büyük olasılıkla iki düğümü doğrudan karşılaştırmak istediğiniz şeyi yapmaz. Muhtemelen, düğümlerde depolanan alanları karşılaştırmak, örneğinnode1.value < node2.value
  2. şu anda, yalnızca üçüncüsü ifdoğruysa saymaya ekliyorsunuz , yapmak istediğiniz şeyin bu olduğundan emin misiniz? Bu arada, eğer deyimin istediğiniz şeyi yaptığını tekrar kontrol etmek isteyebilirsiniz.
  3. Ağaç geçerli bir BST ise yanlış döndürmek istediğinizi varsayalım. Bu, temel bir durumda her zaman doğru veya yanlış döndürmeniz gerektiği ve özyinelemeli aramalarınızın sonuçlarını da döndürmeniz gerektiği anlamına gelir.

Birinci nokta ile ilgili: Bu sahte kod, değil mi? Dolayısıyla, amaç okuyucuya aktarıldığı sürece böyle şeyleri tanımlamak için bir neden yoktur.
sepp2k

@ sepp2k bu doğru, ve benim yorum muhtemelen sahte kod için biraz fazla seçici. Demek istediğim, iki düğümü karşılaştırmanın ne anlama geldiğini anlamamız gerektiğidir. Demek istediğin şu ki bunu zaten örtük olarak anlamalıyız.
Joe

Aynen öyle.
sepp2k
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.