Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Also die Methode soll sein: boolean isVollständig()?
Kannst du da nicht über die Anzahl der Knoten % 2 != 0 gehen? .. war nur grad son Gedanke...
Ansonsten müsstest du den Baum durchwandern bis zu den Blättern und die höhe halt ermitteln
ich gehe davon aus, dass der baum mit verketteten listen implementiert ist?
wenn ja, dann schreibe eine rekursive funktion, die von jedem knoten ausgehend seine beiden unterknoten nacheinander besucht und deren höhe sein, falls der teilbaum volständig ist! anderenfalls false und abbrechen!
die blätter, da die ja keine unterknoten haben, geben 1 zurück und die aufrufende rekursion addiert falls recht-links beides = 1 ist 1 dazu und gibt somit 2 zurück...
die vorangehende rekursion muß also die zurückgegebene höhe der beiden unterzweige vergleichen und dann 1 dazu addieren.... usw.
@ilja,leroy bzw alle: gibt es eine Art "algo" wie man solche rekursiven Schritt für Schritt lößt. ich weiß ja wie die rekursion abläuft nur fehlt es mir schwer Algos dafür zu schreiben.
also Leroy42's Lösung ist FALSCH da sie auch vollständig liefert wenn rechts ein vollständiger Baum hängt und links ein Blatt .. dann ist er aber nicht vollständig...
Was er testet ist ob ein Binärbaum voll, d.h. jeder innere Knoten hat zwei Kindknoten.
Ilja hat genau diesen Test nicht drin sein Algorithmus funktioniert wenn der Baum voll ist....
Ich habe jetzt mal beide gemixt und den code ein wenig gestraft!!
Das Rekursionsende ist jetzt wenn kein Knoten übgergeben wird, d.h. bei einem Blatt bei beiden und wenn ein innerknoten eventuell nur ein Kind hat.
also Leroy42's Lösung ist FALSCH da sie auch vollständig liefert wenn rechts ein vollständiger Baum hängt und links ein Blatt .. dann ist er aber nicht vollständig...
Was er testet ist ob ein Binärbaum voll, d.h. jeder innere Knoten hat zwei Kindknoten.
Soweit schon richtig nur fehlt noch die Bedingung:
und die beiden Teilbäume auch vollständig sind.
Code:
int Baumhöhe(Knoten knoten)
{
if (knoten == null) return 0; // Abbruchbedingung
int links = baumhöhe(knoten.links);
int rechts = baumhöhe(knoten.rechts);
return Math.max(links,rechts)+1;
}
boolean istVollständig(Knoten wurzel)
{
if ( wurzel == null) return true; //wenn kein knoten dann ist der Vollständig :)
boolean antwort;
antwort = (Baumhöhe(wurzel.links) == Baumhöhe(wurzel.rechts));
antwort = antwort && istVollständig(wurzel.links);
antwort = antwort && istVollständig(wurzel.rechts);
return antwort;
}
Dieser Code würde jetzt genau das selbe liefern wie der im Beiträg obendrüber ist nur nicht so effizent, ist aber die genaue Umsetzung des Brainstorming! (Baumtiefe berechnet auch wirklich die Baumtiefe )
Da man jetzt aber die Tiefe der Teilbäume ziemlich häufig doppelt berechnet könnte man sich jetzt überlegen ob man das verbessern könnte!! Allerdings ist der Code oben sehr intuitiv und leicht wartbar was bei größeren Projekten auch einen wichtigen Stellenwert hat.
Das Problem wenn ich beide Funktionen in eine Packen will ist das ich zwei Sachen zurückgeben muss, einmal die Tiefe und einmal ob der Teilbaum vollständig ist. Dieses Problem haben wir in dem Code oben gelöst, indem wir den Tiefenwert missbraucht haben und ihn um ein Flag für den Status, ob er Vollständig ist, erweitert haben.
Man könnte jetzt genausogut dem Knoten um eine Variable Tiefe bzw. vollständig erweitern.
Code:
class Knoten {
Knoten links;
Knoten rechts;
Object value;
transient int tiefe; //transient gibt an das der Wert nicht immer aktuell ist
}
boolean istVollständig(Knoten wurzel)
{
if ( wurzel == null) return true; //wenn kein knoten dann ist der Vollständig :)
//zwingend vor der Tiefeberechnung weil diese sonst noch nicht auf die darunterliegenden Knoten ausgeführt wurde
boolean antwort = istVollständig(wurzel.links) && istVollständig(wurzel.rechts);
// aus dem wird jetzt der Code unten
//if (knoten == null) return 0; // Abbruchbedingung
//
//int links = baumhöhe(knoten.links);
//int rechts = baumhöhe(knoten.rechts);
//
//return Math.max(links,rechts)+1;
if (antwort) {
wurzel.tiefe = 0;
if (wurzel.links != null) wurzel.tiefe = Math.max(wurzel.tiefe,wurzel.links);
if (wurzel.rechts != null) wurzel.tiefe = Math.max(wurzel.tiefe,wurzel.rechts);
wurzel.tiefe++;
}
return antwort;
}
Das ist jetzt nur ein Weg es gibt da sehr viele Möglichkeiten wie man das realisieren will... ein schönes Zitat über objektorientiertes Programmieren dazu
"There are thousand ways to skin the cat"
noch ein paar Tipps:
Übringens kapselt die Zeile boolean antwort = istVollständig(wurzel.links) && istVollständig(wurzel.rechts); eine If-Abfrage ... wenn wurzel.links schon nicht vollständig ist dann wird wurzel.rechts nicht berechnet ..
Wenn man richtig Objektorientiert programmieren will würde man die Funktion istVollständig an den Knoten hängen und nicht ihr einen Knoten übergeben ...
Man sollte eigentlich auch keine Umlaute in Variablennamen stecken .. ich habe es aber jetzt mal der besseren Lesbarkeit trotzdem getan
also ich verstehe nicht warum der code von @ilja falsch sein soll. wenn die inneren Koten nicht vollständig sind liefert er false und wenn die Tiefe aller Blätter nicht gleich ist liefert er false.???