Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Fakultät !!!

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] [ 2 ] > 3 <
020
31.10.2003, 08:43 Uhr
virtual
Sexiest Bit alive
(Operator)


Naja,
Nehmen wir an wir haben einen Baaum basierend auf folgendem Typ (alles ungetestet):


C++:
struct baum
{
    struct baum* kleiner;
    struct baum* groesser;
    int wert;
};


kleiner Enthält den Unterbaum, der die Elemente enthält, die kleiner als wert sind oder ist NULL, wenn kein Wert da ist. Analog gilt das für groesser, das alle Elemente enthält. die gößer als wert sind

Eine suchfunktion in rekursiver art sähe so aus:

C++:
const struct baum* finde(const struct baum* wurzel, int wert)
{
     if (NULL == wurzel || wert == wurzel->wert) return wirzel;
     if (wert < wurzel->wert)
         return finde(wurzel->kleiner, wert);
     else
         return finde(wurzel->groesser, wert);
}


In iterativer form eher so:

C++:
const struct baum* finde(const struct baum* wurzel, int wert)
{
     while (NULL != wurzel && wurzel->wert!=wert)
     {
        if (wert < wurzel->wert)
            wurzel = wurzel->kleiner;
        else
            wurzel = wurzel->groesser;
     }
     return wurzel;
}


Die letztere Variante benötigt jedenfalls weniger Speicher als die erste und auf den meisten Architekturen sollte sie auch schneller sein.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 31.10.2003 um 08:56 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
021
31.10.2003, 12:39 Uhr
~DerLiebeGast
Gast


Gut,aber bei einem kompletten Baumdurchlauf( z.B inorder) muss man sich bei der iterativen Variante,mit einer geeigneten Datenstruktur(z.B eigener Stack),die noch nicht besuchten Knoten speichern und verwalten.
Bei der rekursiven Version wird das implizit gemacht.
Durch den (Extra-) Verwaltungsaufwand dürfte in diesem Fall die iterative Variante auch nicht(oder nur unwesentlich) schneller sein.Der kompaktere Code spricht in diesem Fall also für eine rekursive Lösung.
Binärbäume gehören eigentlich zu den Paradebeispielen für sinnvolle Rekursion.

MfG DerLiebeGast
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
022
31.10.2003, 12:58 Uhr
(un)wissender
Niveauwart


Danke euch beiden, dem habe ich nichts hinzuzufügen, außer diesem.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
023
31.10.2003, 13:32 Uhr
virtual
Sexiest Bit alive
(Operator)


@DerLiebeGast
Auch das geht ganz ohne lokale Variablen. Denn wenn man wirklich sinnvoll iterieren möchte, dann wird man pro knoten einen VErweis auf den Mutterknoten mit speichern, der die erfoderliche Info enthält. Dies würde man unabh. vom rekursiven oder iterativen Ansatz so halten:

C++:
struct baum
{
    struct baum* mutter;
    struct baum* kleiner;
    struct baum* groesser;
    int wert
};

const struct baum* naechster(
    const struct baum* baum)
{
    if (baum->groesser)
    {
        /* Nächster ist als das kleinste Element im
           groesser baum... */

        baum = baum->groesser;
        while (baum->kleiner) baum = baum->kleiner;
        return baum;
    }else if (baum->mutter)
    {
        if (baum->mutter->kleiner == baum)
        {
            /* Nächst größeres Element is also mutter knoten */
            return baum->mutter;
        }else
        {
            /* Nächst größeres Element ist der direkte oder indirekte
               mutter knoten, der uns als kleiner unterbaum enthält. */

            while (baum->mutter && baum->mutter->groesser == baum) baum = baum->mutter;
            baum = baum->mutter;
            if (!baum) return NULL;
            return baum->mutter
        }
    }
    return NULL;
}
/* ungetestet */


Spezielle beim kompletten Baumdurchlauf wird man eh auf die Rekursive Variante verzichten, weil sie zu viele Einschränkungen mit sich bringt: Mit der iterativen Variante schreibe ich einmal zwei Routinen, die mir das erste element gbit und eine die mir das jeweils nächste gibt und kann das universell einsetzen:

C++:
struct baum* element = erstes_element(wurzel);
while(element)
{
   ...
   element = naechster(element);
}


Das geht naturgegebenermassen mit einem rekursiven Ansatz nicht, bzw. macht keinen sonderlichen sinn: man könnte höchstens eine Routine for_each schreiben, die einen Callback enthält zum bearten der einzelnen Elemente:

C++:
void f(struct baum* b)
{
...
}

foreach(wurzel, f);


Wobei man hier dann mit erheblichen Einschränkungen leben muß, was man für Callbaks formulieren darf (hinsichtlich parametern). Ich würde da sehr stark für die iterative Variante plädieren, weil sie hier vermutlich nicht nur schneller, sondern auch deutlich flexibler ist.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
024
01.11.2003, 14:18 Uhr
DerLiebeGast




Zitat:
virtual postete

C++:
struct baum
{
    struct baum* mutter;
    struct baum* kleiner;
    struct baum* groesser;
    int wert
};



Spezielle beim kompletten Baumdurchlauf wird man eh auf die Rekursive Variante verzichten, weil sie zu viele Einschränkungen mit sich bringt: Mit der iterativen Variante schreibe ich einmal zwei Routinen, die mir das erste element gbit und eine die mir das jeweils nächste gibt und kann das universell einsetzen:

C++:
struct baum* element = erstes_element(wurzel);
while(element)
{
   ...
   element = naechster(element);
}





Welche Einschränkungen meinst du? Wenn ich einen inorder Durchlauf haben möchte finde ich Rekursion absolut angemessen.Ich will ja nicht grossartig im Baum rumspringen sondern einen inorder Durchlauf!
Natürlich wäre es Schwachsinn z.B. das Maximum im Baum rekursiv zu suchen.
Sinnvoll wäre aber eine rekursive Suche nach der maximalen Tiefe des Baums.

Ob der Mutterknoten als Hilfsdatenstruktur in die Baumstruktur gehört ist meiner Meinung nach auch ein diskussionswürdiger Punkt.Letztendlich schleppst du die Daten die ich bei der iterativen Variante mit einem lokalen Stack verwalten würde immer mit dir rum.In einem Baum mit n Knoten besteht beim iterativen Durchlauf ein maximaler(temporärer) Speicherbedarf von n/2 Zeigern,mit dem Mutterknoten in der Struktur hast du permanent n Zeiger Speicherplatz belegt.
Jetzt frage ich mal weiter.Was ist denn wenn ich jetzt einen preorder Durchlauf fordere?Packst du dann noch ne bool Variable in die Baumstruktur, um zu verwalten ob der Knoten bereits besucht wurde?
Über das Thema könnte man jetzt ewig diskutieren...


MfG DerLiebeGast
--
if(lesen)
wissen++;
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
025
01.11.2003, 18:55 Uhr
(un)wissender
Niveauwart


Außerdem gibt es da noch die potentielle extra Schleife, um das nächstgrößere Element zu suchen, das entfällt bei der Rekursion.
Ich denke, dass eine rekursive Lösung besser ist, aber es ist immer gut, zur Not auch iterativ den Baum durchlaufen zu können.
--
Wer früher stirbt ist länger tot.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] [ 2 ] > 3 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: