Ja, U-Bahn hatte ein bisschen Verspätung leider und um sowas zu vermeiden,
um möglichst, dass die U-Bahn nicht zu spät sind,
was macht man, man modelliert das U-Bahn-Netz und rechnet darauf rum,
womit modelliert man das Übernetz mit Grafen, dezente Überleitung,
Grafen haben wir schon gesehen, bei Datenstrukturen,
die ersten Folien sind auch primär Wiederholung,
also die ersten 19 Folien oder so,
nochmal dieser Block von den Datenstrukturen,
dass hier nochmal kurz die Begriffe durchgehen könnt und wenn ihr irgendwo denkt,
okay, das kenne ich noch nicht, weiß ich nicht,
dann könnt ihr einmal kurz euch melden,
dann können wir bei dem Begriff tiefer reingehen,
wenn ihr bei jedem Begriff sagt, ja,
kenne ich und so,
also sowas wie Knoten und Kanten oder so kennt jetzt wahrscheinlich jeder,
aber dass man das nochmal alles dann in dem einem Foliensatz zusammen hat.
Also, das hatten wir schon, grundlegende Datenstrukturen,
wird faktisch in, also es ist schweren Bereich zu finden,
wo das nicht mal irgendwie benutzt wird.
Warum? Weil mit Grafen wunderschön irgendwie unterschiedliche Dinge miteinander in Verbindung
setzen kann. Bei allen anderen Sachen ist es so,
so Arrays oder so, ihr habt nur so eine unidirektionale Verbindung,
ihr habt einen Vorgänger und einen Nachfolger und damit kann man sowas ausdrücken wie kleiner und größer oder sowas.
Und beim Grafen könnt ihr halt ausdrücken,
dieses Element ist mit denen acht Elementen in irgendeiner Beziehung und dieses Element nur mit sechs oder irgendwie sowas.
Und damit lässt sich eben viel mehr modellieren,
vor allem, wenn man dann auch sowas dazu nimmt,
wie irgendwie Kantengewichte oder mehrfach Kanten oder so,
dann kann man allen möglichen Kram modellieren, von irgendwelchen Molekülen,
Straßennetze, bei vieler korrigierenden Kurs kann man das modellieren,
kann man alles mögliche machen
Deswegen haben die so eine Bedeutung, wie baut man die formal zusammen?
Da sagt man, so ein Graf G ist so ein Tupel,
bestehend aus der Knotenmenge V und der Kantenmenge E.
Und die Kantenmenge definiert man dann so,
dass man beim ungerichteten Grafen sagt,
eine Kante wird eben ausgedrückt durch so eine Zweiermenge,
bestehend aus zwei Knoten, eine Menge deswegen,
damit ich keine Richtung drin habe, soll ja gerade ungerichteter Graf sein.
Das heißt, die Menge hier sagt einfach,
dass die Knoten V1 und V2 mit einer Kante verbunden sind.
Und beim gerichteten Grafen nimmt man eben Tupel,
damit dann eben drin ist, wenn ich das Tupel V1,
V2 habe, dann habe ich da eine Ordnung drin,
V1 ist der erste Knoten V2,
der zweite,
dann sage ich,
es gibt eine Kante von V1
Heißt das, glaube ich. Nee. Junge,
hier ist die Frage war, ob doppelte Kanten vorkommen können.
Das hier ist ja eine Menge, das ist eine Menge.
Das heißt, du hast gar keine Möglichkeit, doppelte Kanten reinzumachen.
Also die Menge V1V2 kann nur einmal ein E drin sein.
Und genauso das Tubel V1V2 kann da auch nur einmal drin sein.
Das kann ja nicht mehrmals in der Menge drin sein.
Ja. Welche Rückrichtung
Ja, aber hier, das ist eine Menge.
Meine Menge macht die Reihenfolge keine, spielt die keine Rolle.
V1V1V2 ist das gleiche wie V2V1. Ach, deswegen dachtest du mehrfach kannten,
weil die Menge zweimal drin sagt, nee, okay, ja.
Genau, ne? Hier, die Menge V1V2 ist das
Gleiche wie die Menge, V2V1, das heißt,
es kann nur eine Kante zwischen den beiden Knoten geben oder nicht.
Entweder ist diese Zweiermenge drin oder nicht. Genau,
das zu, ne, Knoten V kannten eh.
Jetzt noch die Definition hatten wir in der Datenstrukturvorlesung,
hatte ich die irgendwie nicht drin,
die ist aber auch sehr wichtig,
ne, dass man sagt,
ich kann noch so eine Gewichtsfunktion wehnehmen,
die eben jeder kannte eh
Irgendwie beispielsweise eine Zahl aus R Plus zuordnet,
um eben irgendwie Kosten oder Längen oder irgendwie sowas zu modellieren.
Ich kann das auch anders machen,
statt R Plus irgendwie sowas nehmen wie Sigmar Stern,
dann kann ich jeder kannte ein Wort zuweisen,
dann kann ich die irgendwie beschriften oder ich kann da irgendwie Bilder dran malen oder was auch immer.
Das Wichtige ist, dass ich halt zu jeder kannte,
irgendwie etwas zuordnen kann und dann habe ich halt einen gewichteten Grafen.
Brauchen wir auch nachher ganz oft bei kürzesten Wegen,
Spannbäume und all sowas. Genau,
dann noch so ein paar Begrifflichkeiten, so ein K-Hoch-N,
das soll der vollständige Graf auf Endknoten sein,
sprich entknoten,
die alle
miteinander verbunden sind parweise
Wenn das gerade quasi nicht eintritt, also wenn das bestmögliche Gegenbeispiel eintritt,
sprich, ich habe Endknoten, die alle paarweise nicht miteinander verbunden sind, dann nenne ich die Knotenmenge unabhängig.
Wenn ich so einen Knoten V habe,
dann bezeichne ich mit D von V den Grat des Knotens,
das heißt die Anzahl seiner Nachbarn, mit N von V bin,
nenne ich die Menge der Nachbarn und dann gibt es noch den Minimalgrad und den Maximalgrad,
wenn D von V eben der Grat eines Knotens ist,
dann nehme ich jetzt das kleine griechische D für den Minimalgrad und das große griechische D für den Maximalgrad,
sprich,
ich gucke mir alle Knoten an und gucke mir an,
welcher Knoten hat den minimalsten Grad und das ist mein
Kleingelter von
Und für den maximal gerade genauso. Ich gucke mir alle Knoten an,
wer hat die meisten Nachbarn, das ist der Maximalgrad.
Das sind einfach so zwei Werte, die man manchmal
ganz gut benutzen kann, um bestimmte Grafklassen zu beschreiben.
Wege, die Idee ist jetzt quasi einfach eine Folge von
Knoten zu haben, die mit Kanten verbunden sind.
Das macht man ja so, dass man sagt,
ich habe so eine Menge V mit den Knoten, X0 bis XK.
Und ich habe die Kantenmenge X0 X1, X1,
X2 und so weiter. Also von dem Vorgänger gibt es
immer eins zum Nachfolgende Kante
Ist hier ein bisschen anders geschrieben, dass quasi so diese Kurzschreibweise einfach
die beiden Knoten hintereinander zu schreiben. Da sieht man also,
entweder müssten es Tupel sein oder es müssten Mengen sein,
aber wenn man sich jetzt irgendwie in den Graf-Kontext bewegt,
dann schreibt man relativ häufig die Kanten einfach so,
indem man die zwei Knoten direkt hintereinander schreibt.
V1, V2 ist eine Kante. Passt ja auch zu dem,
was man so spricht. Entsprechend sage ich auch nicht irgendwie,
geschweifte Klammer auf, V1, Komma geschweifte Klammer zu oder so. Ja,
und wenn eben noch die Kante XKX0 dazukommt,
hier auch so eine Kurzschreibweise mit dem Plus,
ich müsste mal vereinigen oder irgendwie sowas,
dann nennt man das eben Kreis,
sprich es gibt einen Weg von X0 bis XK und von
XK gibt es dann eine Kante zurück zu X0,
dann ist das Ganze im Kreis
Ja, und dann noch, wenn ich zwei Knoten XY habe,
dann nenne ich mit B XY, also Distance,
XY, die den Abstand dieser zwei Knoten,
also die geringste Länge eines XY Weges.
Ich gucke mir alle Wege von XY an und den kleinsten
nehme ich und dessen Länge ist dann die XY,
wobei hier Länge so gemeint ist, Anzahl der Kanten.
Da kann man später anders definieren, dass man sagt,
wenn ich Kantengewichte habe, dann subiere ich die Kantengewichte auf,
führe dann irgendwie den kürzesten Abstand zwei Knoten.
Ja, dann die beiden, ja, die brauchen wir auch
gleich nochmal. Wenn ich einen Grafen habe, GVE,
Und ich nehme jetzt aus seiner Knotenmenge V eine gewisse Timinge-V-Strich
raus und aus seiner Kantenmenge eh auch eine Timing-GE-Strich.
So, dass das wieder ein Graf ist. Also es macht jetzt keinen Sinn,
die Knoten von 0V1 rauszunehmen oder als Kante irgendwie V3,
V4, weil dann ist das eine Kante, die mit keinen Knoten eigentlich zusammenhängt.
Das macht keinen Sinn. Also gehstrich selbst soll ja auch wieder
ein Graf sein. Sprich, alle Kanten in E-Strich,
deren enden müssen jeweils auch ein V-Strich drin sein.
Sonst macht das keinen Sinn. Und dann nenne ich gehstrich
eben Teilgraf. Sprich, was ihr macht, ist,
ihr guckt euch einen Graf an und ihr bestimmt jetzt irgendwie
eine beliebige Anzahl von Knoten.
Und dann nehmt ihr noch eine beliebige Anzahl von Kanten,
die irgendwie zwischen diesen Knoten liegen dürfen.
Und das ist dann Teilgraf
Bitte? Ob beliebig auch keine heißt, ja.
Das ist der Spezialfall des leeren Grafen. Also,
wenn ich nur eh leer mache, oder E-Strich,
wenn ich nur E-Strich leer mache, aber Knoten nehme,
dann habe ich einen Teilegrafen, bei dem zumindest Knoten irgendwie drin sind.
Das kann auch manchmal interessant sein, damit ich sagen will,
dass da eine unabhängige Menge drin ist.
Dann sage ich vielleicht, dieser Teilgraf bestehend aus den Knoten
V1 bis V5 ist nur unabhängige Menge.
Dann würde ich halt keine Kanten da irgendwie rausnehmen oder so.
Wenn ich das irgendwie benutzen will so. Und wenn ich
V-Strich leer mache, dann ist E-Strich automatisch auch leer,
dann habe ich einen leeren Grafen.
Das braucht man höchstens mal, wenn man irgendwie so,
keine Ahnung, Induktionsbeweise führen will und sondern einfach einen Induktionsanfang
haben will oder irgendwie sowas
Genau, und ja, da nimmt man also dann irgendwie Knoten und Kanten raus.
Und das darf man aber quasi noch völlig beliebig machen. Das heißt,
wenn ihr vorher sowas habt wie V0, V1,
V2 und alle sind miteinander verbunden, so, also sprich,
ich habe ein Dreieck, dann wären Teilgraf,
auch wenn ihr jetzt V0, V1, V2 rausnehmt,
also alle Knoten,
aber irgendwie nur eine von den Kanten.
Das ist okay als Teilgraf. Diese induzierten Grafen,
die unterscheiden sich jetzt so, dass ihr quasi aus dem
Grafen eine Knotenmenge rausnehmt, also das V-Strich.
Und als Kanten nehmt ihr jetzt alle Kanten aus dem
ursprünglichen Grafen, die irgendwie zwei von diesen Knoten verbinden
Das ist dann von dieser Knotmenge induzierte Teilgraf. Also gegeben
großer Graf. Ihr nehmt ein paar Knoten wählt ihr aus,
sagt ihr, die wollt ihr alle haben.
Und dann guckt ihr quasi in dem ursprünglichen Grafen,
wenn ihr euch nur auf diese Knoten einschränkt,
welche Kanten gehören zu diesen Knoten.
Also welche Kanten haben beide Enden bei diesen Knoten und die nehmt ihr raus.
Und dann habt ihr euren induzierten Grafen-G-Strich. Brauchen wir heute
, glaube ich, nicht. Heute brauchen wir primär diesen
Teilgrafen, induzierter Graf ist ein bisschen spezieller.
Heute brauchen wir den Teilgrafen nachher
Ja, dann darstellen lassen sie sich jetzt,
wenn man jetzt am Computer denkt, wir wollen irgendwie Algorithmen schreiben und so,
wie lassen die sich darstellen oder wie lassen die sich speichern,
eben entweder mit dieser Addizenzmatrix oder mit der Addizenzliste.
Addizenzmatrix sah dann so aus,
jetzt hat man hier irgendwie diese vier Knoten,
VW X und Y und dann macht man sich eben,
in dem Fall sind es vier Knoten,
dann macht man sich so eine viermal vier Matrix und an
die Stelle VW beispielsweise kommt jetzt genau dann eine Eins,
wenn die beiden Knoten eben miteinander verbunden sind und wer ist denn nicht verbunden?
YW sind zum Beispiel nicht verbunden,
da kommt dann eine Null hin
Und dann sieht das so aus. Erstmal haben wir einen hauptdiagonalen überall Nullen,
weil jetzt bei diesen ungerichteten Grafen keine Schleifen gab.
Vielleicht braucht ihr ja immer zwei elementige Teile, wegen der Knotenmenge.
Und dann baut man sich da eben irgendwie überall,
wo sie verbunden sind. Einsen hin. Und der einzige Fall,
wo ihr die Kante fehlt, ist ja VW, YW,
das heißt, hier ist die Null bei YW und hier auch bei WY.
Und wenn es ein gerichteter Graf ist, kann man sich schnell überlegen,
dann ist das eben nicht mehr an dieser hauptdiagonalen gespiegelt.
Weil ich dann eben eine Kante von V nach X haben kann,
aber keine von X nach V oder sowas.
Dann habe ich die nur in eine Richtung
Genau, da steht es nochmal, Speicherplatz bedarf halt in V-Quadrat immer,
weil hier immer so eine V mal V-Matrix habe.
Das ist also unabhängig von der Kantenzahl, habe ich immer den gleichen Speicherbedarf.
Wenn der jetzt dünn ist, der Graf, sprich,
wenn ich im Verhältnis zu V relativ wenig Kanten habe oder im Verhältnis zu V-Quadrat relativ wenig kannten,
dann lohnt sich das nicht so richtig,
das als Addizenzmatrix noch zu schreiben,
weil ich dann eben relativ viel Speicherplatz verschwende.
Also wenn ich irgendwie tausend Knoten habe und ich habe vielleicht nur 5000 Kanten so,
das sieht ja im Verhältnis auch schon mal ganz gut aus,
aber dann würde ich bei der Addizenzmatrix irgendwie eine Million Speicherplatze irgendwie verbrauchen,
also eine Million Kästchen an der Matrix haben,
ich brauche nur 5000 davon,
das ist irgendwie Verschwendung,
kann ich
mir vorstellen
Deswegen, da dann die Addiatienzliste, hier einfach mal am
gleichen Beispiel, aber die würde man jetzt benutzen,
wenn das irgendwie dünn besiedelt ist.
Da ist die Idee, ich habe wieder für die Knoten,
für die Entknoten, so ein Arry.
Und jedes Element des Arris zeigt jetzt auf eine Liste der Kanten,
mit denen dieser Knoten verbunden ist. Also V,
der Knoten V zeigt auf die Liste W XY,
weil der eben mit den Knoten wie XY verbunden ist.
W ist nur mit V und X verbunden und so weiter.
Da kann man sich schon vorstellen, ich spare Speicherbedarf,
wenn ich irgendwie weniger Kanten habe.
Das Blöde ist aber rauszufinden,
ob zwei Knoten
miteinander benachbart sind
Wenn ich zwei Knoten kriege, dann kann ich in einer Atdiazenz-Matrix,
wenn ich das jetzt als Arry speichere,
was man üblicherweise tut, kann ich relativ schnell nachgucken,
ist deine Kante oder nicht.
Ein Zugriff, zack, weiß ich es.
Steht da eine Eins, ist da eine Kante,
steht da eine Null, ist ja keine.
Wenn ich das hier machen will und ich kriege diese zwei Knoten,
dann kann ich das nur so machen,
indem ich zu einem von dem Knoten die alte Azenzliste gehe und dann unter Umständen eben die ganze Atdiazenzliste durchgehe.
Im Worst Case brauche ich dann irgendwie OV-Zeit,
um irgendwie, die hat ja Azenzliste durchzugehen.
Während ich bei dem anderen in eine O1 bin,
also ein Schritt, fertig.
Genau, da steht es auch nochmal hier,
Speicherbedarf ist in Täter V plus E,
das V kommt von dem hier
Von dem Array für die Knoten links und das plus eh eben,
weil man ja für jede Kante hier ein Element in
den Listen hat.
Genau. Mattiazenz Matritzen hat die Azenzlisten.
Da nochmal die Zusammenfassung
Hier habe ich gar nicht erzählt. Bei dem dritten Punkt dafür ist es langsamer,
alle Knoten zu bestimmen, die mit einem Knoten benachbart sind.
Wenn ihr das bei einer Art Jazzenzmatrix machen wollt,
also wenn ihr sammeln wollt, mit dieser Knoten,
gegeben, mit welchen Knoten ist der verbunden,
dann müsst ihr quasi die ganze Zeile,
da hat ja Azenzmatrix durchgehen, um zu wissen,
mit wem da alles benachbart ist.
Weil da hat ja Azenzliste, nehmt euch einfach die Azenzliste und wisst es,
oder wandert ihr halt die Azenzliste durch oder so.
Das ist dann nur so aufwendig, genauso aufwendig, wie viele Nachbarn er hat.
Wenn er irgendwie 5.000 Knoten habt und ihr habt einen Knoten,
der hat fünf Nachbarn, dann müsst ihr bei der Addiazenzmatrix
eben trotzdem diese 5.000 Knoten checken und gucken,
ob er mit denen benachbart ist.
Bei einer Addiazenzliste geht ihr einfach durch die Saddiazenzliste drüber,
wenn ihr nur die Länge fünf hat,
braucht ihr halt
nur fünf Schritte
Also also beides so seine Vor- und Nachteile ist in einer Transformierbar.
Ist jetzt aber nicht so, dass man,
nehmen wir mal an, man liest aus irgendeinem Datensatz einen Grafen raus,
dass man jetzt unbedingt als nächstes sagt, hui,
jetzt transformiere ich das, damit ich beide Darstellungen habe,
weil das eben auch teuer ist.
Also das würde man jetzt auch nicht unbedingt machen.
Oder halt nur, wenn es wirklich einen guten Grund gibt.
Gut, das zu den Grundlagen davon fragen.
Hoffen, gut. Dann wollen wir jetzt was Neues machen.
Das kennt ihr wahrscheinlich auch schon, Tiefensuchung und Breitensuche,
kennt ihr? Wir kennen irgendeinen, wer kennt Tiefensuche
Wer kennt Breitensuche? Finde ich gut, dass einige Hände nicht
bei beiden sein oben sind. Nur ganz erstaunlich. So,
wir machen das mal ein bisschen trotzdem im Detail,
weil wir das ein bisschen anreichern wollen, so wie man das üblicherweise,
wenn man jetzt nur grob die Idee macht, nicht tut.
Also wir wollen da noch ein bisschen mehr Daten sammeln,
während wir quasi den Breitensuchbaum und den tiefensuchbaren bestimmen.
So, was machen wir? Wir wollen was über die
Struktur des Grafen herausfinden. Dazu wollen wir den durchwandern.
Das hat auch den Vorteil, wenn wir den durchwandern,
dass wir alle Knoten einmal besucht haben.
Wenn wir alle Knoten mal brauchen, ist das praktisch.
Und gleichzeitig bauen wir so einen Spannbaum auf.
Ein Spannbaum ist ein Teilgraf des Grafen
Wobei das eben ein Baum sein soll und alle Knoten von G enthält.
Was ist der Vorteil bei diesem Baum? Was habe ich
damit erreicht? Also warum nehme ich nicht was anderes?
Könnt ihr auch irgendwie Kreise da einbauen und so.
Das ist der Vorteil vom Baum?
Ihr könnt in dem Baum lustige Dinge tun, ja.
Wir können im Kreis aber auch lustige Dinge tun,
da hat sie nämlich keinen Kreis. Der Vorteil ist die Frage,
ist ein bisschen doofgestellt, aber der Vorteil ist halt,
das ist in dem Sinne minimal, als das,
wenn ihr alle Knoten haben wollt,
braucht ihr mindestens N-Minus 1 Kanten
Ich meine, wenn ich zwei Knoten habe,
brauche ich eine Kante, wenn ich drei Knoten haben würde,
dann brauche ich zwei Kanten,
wenn ich die irgendwie verbunden haben will und so.
Und ein Baum hat ja gerade bei Endknoten end minus eins Kanten.
Das heißt, das ist minimal in der Anzahl der Kanten,
die ich da jetzt gerade aufgesammelt oder irgendwie traversiert habe und so.
Das ist praktisch. Für später dann auch.
Deswegen sind Spannenbäume immer so nett. Ja, warum macht
man das überhaupt? Breiten Tiefensuche, vor allem,
wenn man jetzt irgendwie das vielleicht kennt oder irgendwie aus Library-Funktionen
sammelt.
Deswegen hier, Urtypen
Manchmal hat man die bei anderen Graf-Algorithmen komplizierteren Graf-Algorithmen erstmal irgendwie als Subroutine drin,
damit man erstmal was weiß über die Struktur des Grafen.
Kann beispielsweise auch wichtig sein, wenn ich einen Spannbaum bestimme.
Und ich merke dann irgendwie, okay, mein Spannbaum hat von
den 5.000 Knoten, die hier rumflattern, irgendwie nur 4.800.
Dann weiß ich, die anderen 200 sind irgendwie gar nicht
erreichbar von bestimmten Startpositionen aus, sondern die bimmeln nochmal irgendwo rum.
Dann weiß ich, mein Graf ist unter Umständen irgendwie kaputt,
wenn ich denn einen richtigen vollständigen Zusammenhängegraf haben wollte.
Für sowas ist das irgendwie praktisch. Und eben auch als Ideengeber,
weil man irgendwie da bestimmte Algorithmenmuster so ein bisschen eintrainieren kann,
die für Grafen halt immer wieder mal auftreten
Genau, deswegen machen wir das. Was ist die Idee
bei der Breitensuche? Ihr fangt mit dem Startknoten an,
entweder ist der gegeben oder ihr nehmt einfach irgendeinen Knoten als Startknoten
, sagt, so das ist jetzt mit Startknoten so.
Und dann ist die Idee, seine Nachbarn seht ihr ja,
also nehmen wir Mani hat das als Lizenzliste gegeben,
und ihr habt jetzt einen Knoten V,
dann geht in seine Art Azenzliste, die Knoten kennt ihr alle.
Jetzt nehmt ihr quasi die alle erstmal auf und sagt,
okay, die habe ich jetzt alle entdeckt, die sehe ich alle.
Jetzt nehmt ihr euch einen davon und sagt, okay,
was hat der denn noch so als Nachbarn, also neue Nachbarn?
Dann schreibt ihr euch die alle auf.
Und damit ihr jetzt wirklich in die Breite geht,
der entdeckt ja jetzt Knoten,
die vom ursprünglichen Startknoten
zwei Schritte entfernt sind
Also die, die neu dazugekommen sind. Damit ihr jetzt eine Breitensuche macht,
guckt ihr euch jetzt nicht als nächstes dessen Nachbarn und
dessen Nachbarn und dessen Nachbarn an oder so,
sondern ihr guckt euch jetzt als nächstes wieder von den vorher schon mal entdeckten Knoten,
von denen wieder die Nachbarn an.
Damit ihr so nach und nach alle Knoten entdeckt,
die Abstand eins haben, die Abstand 2 haben,
die Abstand 3 haben und so weiter.
Wie macht man das? Ich starte mit dem Startknoten,
packe den in eine Q und jetzt mache ich das folgende,
ich nehme den jetzt raus aus der
Und... Ja, wenn ich will,
bearbeite ich die noch oder sowas. Und das Wichtige,
aber so das, was jetzt die Breitensuche halt ausmacht,
ich packe jetzt alle seine Nachbarn,
auch in diese Q. Und den schmeiße ich raus aus der Q.
Jetzt sind alle seine Nachbarn in der Q. Und da ich das jetzt so weitermache,
besuche ich jetzt ja zuerst alle seine Nachbarn,
weil die jetzt quasi vorne in der Q sind.
Und deren Kinder packe ich ja immer hinten an die Q ran.
Das heißt, ich kriege so Schritt für Schritt erst alle Knoten,
die Abstand eins haben, alle Knoten,
die Abstand zwei haben und so weiter.
Durch die Knoten, Q wird sichergestellt,
dass die Knoten in der Breite besucht werden.
Also zunächst werden die Knoten mit Entfernung K von S
entdeckt und dann die mit Entfernung K plus
Bei dem Beispiel hier, dass die Folie davor ist
nur zur Nachbereitung, das erzähle ich jetzt ja.
Bei dem Beispiel hier ist das mal einmal als Baum gegeben,
danach machen wir das nochmal als Graf, damit man einmal sehen kann,
wie das tatsächlich in der Breite durchsucht wird.
Das wird jetzt quasi Ebene für Ebene abgearbeitet und immer in der Breite.
Deswegen heißt das Breitensuche. Wenn ich bei 10 anfange,
dann entdecke ich eben zuerst die Knoten 6 und 14,
dann die Knoten 3, 8, 12,
15 und dann halt die letzte Ebene und so,
dann entdecke ich die halt Schritt für Schritt.
Wenn ich jetzt also bei 10 anfange,
was ist natürlich so ein bisschen,
der Anfang könnte bei beliebigen Knoten sein,
aber damit das jetzt illustrativ ist,
fangen wir mal oben bei der 10 an
Und dann fange ich irgendwie hier bei der 10 an.
Das hier soll die Q sein, das mit Kuh markierte und
das mit A markierte, ist quasi die Ausgabe oder so.
Wenn ich bei der 10 anfange,
dann packe ich die in die Q,
ja gleich als nächstes nehme ich die quasi raus und sage,
okay, was sind seine Kinder? 6 und 14,
dann packe ich 6 und 14 in die Q und sage,
jetzt bin ich mit der 10 fertig und gebe die irgendwie aus.
Jetzt nehme ich als nächstes die 6, pack. Moment,
ja genau, ich nehme die 6,
packe deren Kinder in die Q,
also 3 und 8 und gebe die 6 aus,
ne?
Soll ich mal kurz überlegen? 1619, 38? Ja, genau.
Jetzt nehme ich die 14, wieder aus der Q,
steht hier vorne, 14, Kinder sind 12 und 15,
packe ich die in die Q und gehe die 14 aus.
Als nächstes an der Q ganz vorne, die 3,
nehme ich die 3 aus der Q,
Kinder 2 und 5, packe ich die in die Q,
gebe die 3 aus, fertig.
Dann irgendwie die 8, 7 und 9,
die Kinder in die Q tun, 8 ausgeben und immer so weiter, ne?
Jetzt bin ich da drüben bei der 12. Das Schöne ist
auch durch diese Q, ihr habt euch quasi gemerkt,
wo ihr in diesem Baum seid, ne? Normalerweise,
wenn ihr das irgendwie jetzt so mit rekursiven Aufenrings sowas macht,
dann müsste man hier eventuell von der 8 überhaupt erstmal wieder
da hinkommen
Und das ist halt in der Q gespeichert, dass ihr
gerade bei dem Knoten seid und da direkt hinspringen könnt quasi.
Genau, da zwei Schritte auf einmal,
wenn ich zwölf aus der Q nehme,
packe ich 13 in die Q, dann nehme ich 15,
packe die 16 in die Q. Deswegen hier in der Reihenfolge 13 und 16.
Und bei denen passiert jetzt nichts mehr Großes,
weil die keine Kinder mehr haben.
Ich nehme jetzt nach und nach 2, 5, 7,
9, 13 und 16 und gebe die alle aus.
Und wenn ihr das jetzt vergleicht hier,
wie der Baum aussieht und wie das hier im Array aussieht,
dann hat ihr das quasi Ebene für Ebene und immer von links nach rechts ausgegeben.
Deswegen Breitensuche.
Etwas in der Breite des Baumes durchsucht
Kernidee, wir färben erstmal einen Knoten, den Startknoten,
er kriegt jetzt die Farbe pink, dann tut er den in eine Q,
am Anfang ist die Q leer und dann packt er da halt erst rein und jetzt macht ihr immer,
solange die Q noch nicht leer ist,
nehmt ihr den Kopf der Q aus der Q raus und dann guckt ihr euch jeden Nachbarn von U an und wenn der noch weiß ist, sprich,
wenn er bisher noch nicht abgearbeitet ist und noch nicht in der Q drin ist,
dann macht ihr den pink und packt ihn in die Q und dann,
wenn ihr jetzt mit der Forschlife hier fertig seid von den Zeilen, fünf bis zehn,
dann habt ihr ja quasi alle Nachbarn von U euch angeguckt,
dann habt ihr U entdeckt und alle seine Nachbarn entdeckt,
dann könnt ihr sagen, okay, mit U bin ich fertig,
deswegen kriegt er da die Farbe schwarz.
Also im Grunde genommen weiß noch nicht entdeckt,
pink entdeckt, aber noch nicht abgearbeitet und schwarz abgearbeitet
Also entdeckt und abgearbeitet. Das ist die Idee dabei.
Das ist so die Kernidee von der Breitensuche und jetzt kann man
diese Breitensuche halt gleich noch ein bisschen mit mir Infos anreichern,
damit man noch so Sachen machen kann, wie zu einem beliebigen Knoten,
ein Pfad vom Startknoten zu diesem Knoten zu wissen.
Weil bisher, wenn ihr euch das hier noch anguckt,
das ist zwar schön, dass sich die Knoten jetzt so ausgegeben habe,
aber ich habe überhaupt keine Infos über den Spannbaum.
Also wenn das jetzt wirklich ein Graf wäre und ich hätte jetzt diesen,
wenn ihr euch vorstellt,
hier sind noch ganz viele Kanten irgendwie zwischen den ganzen Knoten,
dann wäre das jetzt zwar der Breitensuchbaum, den ich irgendwie bestimmt hätte,
so, aber ich habe den Baum gar nicht,
ich habe nur die Knoten gerade ausgegeben.
Den Baum würde ich vielleicht auch haben,
damit ich damit
nachher arbeiten kann
Dafür muss ich das hier mit Infos anreichern. Es war
auch zur Nachbereitung. Einmal noch ein Beispiel und danach reichen wir das
gleich mit Infos an. Jetzt hier ist ein richtiger Graf,
als würde man die sexy irgendwie als Startknoten nehmen, in dem Beispiel.
Und dann packt man eben die sechs in die Q,
gibt sie aus und packt die Kinder in die Q 2,
3 und 8. Einmal als Anmerkung, die Reihenfolge,
in denen das jetzt da gerade steht,
also in denen das hier in der Q steht,
die ist davon abhängig, wie die Knoten in der Addiazenzliste von S stehen.
Wenn die Knoten in der Addiazenzliste von S in der anderen
Reihenfolge stehen, dann kommt da auch eine andere Reihenfolge raus
Weil er ja immer den ersten aus der Diazenzliste nimmt,
den die Q packt, dann die nächsten nimmt,
den die Q packt und immer so weiter.
Nee, einfach irgendeinen Knoten als Startknoten wählen, ist beliebig.
Ja, Mr. Knoten 2, ne? Ich nehme immer
den vordersten Knoten aus der Q, nehme ich also die 2 raus.
Kind ist die 10. Natürlich die 10 ganz hinten in
die Q und geht die 2 aus.
Also zwei rausnehmen aus der Q, 10 reintun,
zwei abarbeiten,
Und es tritt dieser Fall auf,
dass ich jetzt den Knoten 3 nehme und dann gucke ich
mir von 3 die Nachbarn an und dann stelle ich fest,
da eine Nachbar schwarz, der andere Nachbar ist pink,
aber keiner davon ist weiß.
Also packe ich nichts Neues in die Q rein.
Nämlich also quasi die 3 einfach raus aus der Q
und gebe die in die Ausgabe.
Bei der 8 entdecke ich 7 und 9. Bei der Zähne
decke ich wieder gar nichts. Jetzt mache ich zuerst die 7,
da entdecke ich nochmal die 5 und dann 9 und 5 einfach abarbeiten.
Und wenn ihr euch jetzt das Ausgabe Arry anguckt,
dann stehen die Knoten da eben geordnet nach dem Abstand,
nach dem kürzesten Abstand,
den sie von S haben
Also der Knoten 8 beispielsweise,
der kommt vor der 10, weil der Knoten 8,
der kürzeste Weg von S zu dieser 8,
das ist eben Pfad der Länge 1.
Und zur 10 brauche ich mindestens zwei Schritte.
Und genauso sind die sortiert, ne? Knoten,
der erste Knoten, die 6, die hat Abstand,
null. Die nächsten drei haben Abstand 1. Die nächsten drei
haben Abstand 2 und der letzte hat Abstand 3. Genau.
So, und jetzt wollen wir diese Breitensuche anreichern mit Infos.
Fragen bis dahin. Breitensuche, gut. Jetzt wollen wir
Folgendes machen. Wir arbeiten wieder mit Farben
Statt pinken im Kormen grau. Weiß heißt weiterhin noch nicht
besucht. Grau heißt, habe ich schon entdeckt,
aber ich habe die Nachbarn noch nicht. Schwarz heißt,
ich habe den besucht und ich habe alle Nachbarn entdeckt.
Also im Grunde genommen, so ähnlich wie eben auch,
nur dass ich eben pink statt grau genommen habe.
So, und was merkt man sich noch? D von U,
also hier Daris D, das ist die Distance, also die Entfernung,
die der Knoten vom Startknoten S hat, kann man auch manchmal brauchen.
Und was wir vor allem brauchen, ist dieses P,
Pi eigentlich für Pi und dann Vorgänger, um sich zu merken,
was der Vorgänger von dem Knoten-U jetzt in dem ersten Initialisierungsstar ist.
Was der Vorgänger von U ist, auf einem Pfad von S zu U.
Wenn ich für jeden Knoten seinen Vorgänger habe auf diesem Pfad,
dann kann ich daraus den Baum rekonstruieren.
Dann kann ich mir einen liebigen Knoten nehmen,
kann immer diese Pi-Kanten entlang gehen und kommen zum Startknoten.
Wenn man was machen will, der Anfang ist klar,
ich mache alle Knoten weiß, die Entfernung ist unendlich,
weil bisher weiß ich die noch nicht und der Vorgänger ist Nil,
weil weiß ich auch noch nicht.
Dann nehme ich mir diesen Startknoten-S, den mache ich grau,
sagt, die Distanz ist null,
weil von sich selbst hat er eben die Distanz null und der Vorgänger ist Neil,
damit kann ich auch nachher immer einmal über alle Knoten ruhig gehen und die Wurzeln rauskriegen,
wenn ich das mal bei irgendwas brauche.
Und dann genauso wie eben auch, ne,
Liste am Anfang leer und ich tue es in die Liste.
Jetzt kommt der interessantere Hauptteil, solange die Q noch leer ist,
nehme ich immer den Kopf der Liste und jetzt gehe ich auch,
genauso wie eben auch alle Nachbarn durch.
Und was ich jetzt aber mache, ist, wenn der,
nur wenn der weiß ist, genauso wie ihm auch,
nur dann passiert was, dann mache ich den eben grau
Und jetzt hier in Zeile 6, da ist das, was eigentlich passiert.
Da sage ich jetzt bei diesem neuen deckten Knoten,
der hat ja Distanz eine mehr als mein Vorgänger.
Ich habe den von V aus entdeckt. Also bin ich,
wenn V3 Schritte weg ist von S,
dann bin ich jetzt vier Schritte weg.
Und gleichzeitig merke ich mir, dass mein Vorgänger der Knoten-Uhr ist.
Ach, ich habe das eben falsch schon gesagt.
V habe ich entdeckt. Also wenn ich bisher zu U
die Länge 3 hatte, dann habe ich jetzt zu V
die Länge 4 und von V der Vorgängers EMU.
Ja, und der Rest ist ganz genauso.
Natürlich V wieder eine Q und macht die Farbe von U
schwarz, weil ich den jetzt abgearbeitet habe.
Auch da so ein Beispiel
War mit S an. Entfernung Null. Jetzt kann ich irgendwie
A und C entdecken. Neben S aus der Cue raus,
packe A und C rein, A und C kriegen als
Distanzwert 1 und als Vorgänger beide den Knoten S.
Jetzt illustriert gleich durch so dicke Kanten, dass man weiß,
das hier sind jetzt quasi Baumkanten irgendwie, diese dicken.
Jetzt war das in der Art Lizenzliste von S so,
dass A eben vor C kam.
Deswegen wurde A als erstes in die Q gepackt.
Wird jetzt als erstes in die Q gepackt. Wird jetzt
als erstes rausgenommen und dann entdecke ich eben B von A aus und nicht von C.
Da sieht man auch irgendwie dieser Breitensuchbaum ist nicht eindeutig,
sondern hängt irgendwie davon ab, wie die mit welchem Klo
ich anfange und vor allem aber wie die Alterzenzlisten irgendwie gegeben sind.
Und jetzt würde man eben von A aus das B entdecken,
dann kriegt B den Wert 2 und hier kommt so eine dicke Baumkante zwischen A und B hin.
Und außerdem entdecke ich noch E. Genau,
unternehme ich C, entdecke von C aus das F,
hat dann auch die Entfernung 2. Ist auch gut,
dass ich das nicht irgendwie von E entdecke,
dann hätte ich da plötzlich die Entfernung 3,
das ist irgendwie doof.
Ja, von B aus passiert nichts und von E aus
entdecke ich die und von F aus entdecke ich gehe
Ja, genau, ich das jetzt so,
ich meine, man sieht,
da sind keine Kreise drin und ich habe irgendwie alle Knoten erwischt,
also ist das irgendwie ein Baum,
aber wenn man sich das irgendwie vorstellt,
man zieht das Esther jetzt so raus,
dann habe ich eben den Knoten Est,
der hat die zwei Kinder A und C,
A hat als Kinder B und E,
C hat als Kind F und dann hat eben irgendwie eh noch als Kind D und F noch G,
also habe ich irgendwie so einen Baum.
Kein besonders schön, aber ich habe einen Baum. Ja,
Laufzeit, ja, kommt nachher auf V plus eh raus,
warum jeder Knoten es zu Anfang weiß
Und dieser Test in der Schleife stellt sicher, dass jeder Knoten
nur genau einmal in die Q reingetan wird und einmal wieder rausgenommen wird.
Das heißt, diese NQ&DQ-Operation, die werden genau U von V mal aufgerufen.
Also für diese Warteschlangen-Operation brauchen wir genau hier O von V Schritte,
also zwei mit V eigentlich. Dann wird auch,
weil ja jeder Knoten nur einmal aus der Q rausgenommen wird
und alle seine Nachbarn bestimmt werden.
Das mache ich ja nicht mehrmals. Ich gehe also in jede Adlizenzliste
genau einmal rein und gucke mir alle Knoten in die seid ihr Adzenzliste an.
Das heißt, jede Adlizenzliste wird nur einmal geprüft. Also Summe,
aller Adlizenzlisten ist auch in diesem O von E folglich,
braucht das Prüfen auch irgendwie O von
Da kann man sich überlegen, hier,
ich habe O von V Warteschlangen-Operationen,
ich habe O von E-Operationen und mit den Additizenzlisten zu arbeiten.
Mehr passiert da auch nicht. Initialisierung geht auch noch in O von V.
Und dann bin ich insgesamt in diesem O von V plus E.
Stimmt nur, wenn das in ADAZenzlisten gegeben ist,
wenn das als ADAZenz-Martritzen gegeben ist, dann muss man sich nochmal angucken,
wie die Laufzeit ist, dann wird die ein bisschen schlimmer.
Weil ich dann für das Durchgehen in der Additizenzliste ja irgendwie,
oh, von V viele Schritte brauche.
Korrektheit. Korrektheit kann man mittelschleifen in Variante zeigen. Schleifen in der Wellen,
die irgendwie sagt, dass die Q gerade aus der Menge der grauen Knoten besteht,
weil die Q nachher irgendwann leer sein muss,
weiß ich, es gibt keine grauen Knoten mehr,
wir müssen die weiß oder schwarz sein,
wenn die zusammenhängt, wenn er gerade zusammenhängt,
ist das alles schwarz und dann kann ich halt Stück für Stück irgendwie die Korrektheit dieser Breitensuche zeigen.
Der Satz klingt dann da so ein bisschen umständlich,
da steht im Grunde genommen nur,
ich habe alle erreichbaren Knoten ermittelt, die Distanzwerte,
die da stehen, die von V,
die stimmen gerade mit diesem Delta überein,
also mit dem Kürzes,
mit der kürzenden Entfernung von S zu V und über die Peace
kriege ich eben gerade einen kürzesten Pfad dann
Auf der nächsten Folie steht es nochmal zur Betonung in der Box,
weil hier irgendwie, da habe ich so klein hingeschrieben,
siehe Corman, da steht es nochmal dick,
also lest es nochmal nach im Kommen in den Beweis,
das sind so irgendwie zweieinhalb, drei Seiten,
da ist sie ein gutes Gefühl dafür kriegt,
wie man das da beweisen kann in einem recht eingängigen Setting,
weil wie der Algorithmus funktioniert, ist einem relativ schnell klar,
auch dass das irgendwie alles passen müsste mit den Abständen und so,
wird einem mit dem Beispiel relativ schnell klar und dann,
dass sie das einmal nachlest.
Fragen. Lass alles zur breiten Suche.
Fragen, Fragen, Fragen
Das machen wir im Geist. Was machen wir,
wenn wir einen gerichteten Grafen haben? Erstmal geht es uns
nur um die Bestimmung, also um die Struktur des Grafen.
Da sind mir die Gewichte erstmal egal. Wenn ich diese Breitensuche jetzt mache,
um erstmal irgendeinen Spannbaum zu haben, wegen der Struktur des Grafen,
dann ist mir das mit dem Gewicht ja egal.
Wenn ich später Sachen mit dem Gewicht machen möchte,
also wenn ich dann so Sachen machen möchte,
wie viel weit entspannenden Baumstimmen, aber ich will einen minimalen Spannbaum bestimmen,
dann brauche ich einen anderen Algorithmus.
Was sonst noch
Was ist, wenn man bei einem gerichteten Grafen,
Knoten, als Startknoten aussucht, der nicht alle erreicht?
Dann die Breitensuche hier wurde so illustriert, dass wir
einfach nur gesagt haben, wir bestimmten so einen Breitensuchbaum.
Bei der Tiefensuche gehen wir gleich genau darauf ein.
Aber so was meinen, kurz und knapp, du bestimmst dann einen Breitensuchwald.
Das heißt, du bestimmst dann einmal von deinem Knoten aus
ein paar Knoten, also einen Teil des Grafen.
Und dann fängst du von denen, die immer noch weiß sind,
an und suchst davon wieder irgendeinen raus und besuchst bestimmt es
auch von dem einen Breitensuchbaum.
Ja, du warst weiter. Ja,
lass weiter
Du nimmst von denen, die noch weiß sind, ja,
das ist ja das, was dich stört, das noch knotenweiß sind.
Du nimmst von denen, die noch weiß sind,
einen Knoten und startest den Algorithmus nochmal.
Ja, deswegen Wald. Mehrere Bäume sind ein Wald.
Beim gerichteten Graphen, was das Problem dabei bei einem gerichteten Graphen,
also wenn man das so macht, wie ich das eben erzählt habe.
Ich glaube, es bringt einem nichts zum Baum,
weil man weiß ja nur,
welche Knoten von meinem Start wohl erreichbar sind,
aber die anderen... Genau, man weiß nur,
was von meinem Startknoten aus erreichbar ist,
aber die anderen Richten weiß man irgendwie nicht so
Ob es einem nichts bringt, so bringt einem schon was,
man hat dann halt einen Wald so,
aber bei diesen gerichteten Grafen ist das unter Umständen nicht so optimal,
wenn es mir jetzt wirklich so,
also optimal in dem Sinne von, vielleicht kann ich,
wenn ich vom anderen Knoten aus starte, alle Knoten erwischen.
So, und dann habe ich quasi,
was die Struktur angeht, einen richtig schönen Baum,
weil ich weiß, von dem aus,
von dem Staat heraus kann ich alle anderen erreichen, so, ne.
Bei dem anderen Ding sammle ich jetzt vielleicht irgendwie Bäume. Also Extrembeispiel,
wenn ihr noch an dieses Beispiel denkt,
mit wo der Baum gegeben war und ich habe ja bei der Wurzel angefangen,
ne, wenn man da jetzt dieses Verfahren macht und ich fange bei den Blättern an,
dann sagt jedes Blatt erstmal,
oh,
ich bin mein eigener Baum
So, jetzt werden die alle schwarz. Dann gehe ich
eine Ebene höher und fange bei denen an.
Dann sagt jeder von denen auch, ich sehe nichts mehr,
was noch nicht schwarz ist.
So, die werden auch alle ein einzelner Baum.
Dann habe ich nur Bäume. Also dann ist jeder Knotenbaum
. Das ist eine Katastrophe, ne? Deswegen war das
Beispiel mit dem Grafen auch mit einem Ungerichteten,
weil bei Ungerichteten ist das irgendwie nice, ne?
Bei Gerichten ist das ein bisschen problematischer. Ja. Nachfragen.
Breitensuche. Dann sind wir mit der breiten Suche fertig.
Dann kommt diese Tiefensuche. Ähm, ähnliche Idee. Bei
der Breitensuche habe ich gesagt, ich fange mit dem Startknoten an.
Ich gucke mir alle Kinder an
Jetzt mache ich bei den Kindern sukzessive das Gleiche.
Deswegen in die Breite gehen. Bei der Tiefensuche sage ich,
ich will zuerst in die Tiefe gehen. Das heißt,
ich fange wieder mit dem Knoten an, nehme seine Kinder und
von einem Kind nehme ich mir jetzt wieder die Kinder.
Und von einem dieser Kindeskinder nehme ich mir jetzt wieder die Kinder
und von einem dieser Kindeskindeskinder nehme ich mir jetzt wieder die Kinder.
Das heißt, ich wandere erst mal in einen Zweig,
so weit nach unten, wie es irgendwie geht,
bevor ich mir dann wieder irgendwie andere Kinder angucke.
Deswegen Tiefensuche. Ich gehe quasi so ein Pfad so lange in Land,
wie ich irgendwie kann. Und hier steht es auch schon mit diesem Tiefensuchtwald,
wenn unentdeckte Knoten übrig bleiben,
wählt man einen von denen als neu entdeckten Startknoten,
kann man natürlich bei der breiten Suche Raum machen,
aber es ist üblicher,
dass dann quasi mit der Tiefensuche zu machen,
wenn man da mit den Infos mehr anfangen kann
Sehen wir auch nachher bei den Anwendungen,
dass wir bei der Tiefensuche mit den Infos was anfangen kann,
die man dann gewinnt, trotzdem.
Bei der Breitensuche nicht so viel. Wie funktioniert das?
Da steht genau der gleiche Text, bis auf das da.
Da der ersten Zeile, da steht jetzt nicht mehr Q, sondern ein Stack. Ja,
und dann steht da vielleicht noch irgendwie oberster Knoten,
statt vorderster Knoten oder irgendwie sowas so,
aber im Grunde genommen ist es komplett das Gleiche mit dem Unterschied,
dass man jetzt ein Stack statt eine Q nennt.
Ja, warum macht das nachher einen Unterschied bei der Implementierung,
weil man bei der Q die neuen Knoten ja immer hinten anfügen würde
an die Q und dadurch erst dann an sie rankommt,
wenn man die vorderen alle abgearbeitet hat?
Beim Stack kommen die neuen oben drauf, das heißt,
die werden zuerst bearbeitet
Da könnt ihr euch vorstellen,
wenn ich einen Knoten nehme und ich tue alle seine Nachbarn
auf den Stack und ich nehme mir jetzt den ersten dieser
Nachbarn und packe alle dessen Nachbarn auf den Stack,
dann sind die plötzlich oben.
Das heißt, als nächstes kriege ich einen Knoten,
der ein Kind vom Kind ist. Also durch den Sack
wird sichergestellt, dass die Knote in der Tiefe besucht werden.
Genau, jetzt kommt erstmal wieder dieses Beispiel mit dem Baum.
Da, da habe ich irgendwo einen Fehler gemacht,
deswegen ist das hier nochmal dick hervorgehoben mit einer Ausnahme beim Knoten-Szenen
ist genau umgekehrt, das werden wir gleich sehen.
Wenn ich die Zehen nehme und jetzt packe ich die Kinder auf den Stack,
6 und 14, S, in dem S,
wenn es pink ist, ist es in der Q,
ich nehme erst raus aus der Q,
ich packe die Kinder auf den Stack und ich bin fertig,
ich gebe die 10 aus.
Das hatte ich da jetzt irgendwie im Eifer, das Gefecht ist
genauso gemacht wie bei der Breitensuche. Hier ist es jetzt ja so,
wenn die 6 oben sein soll auf dem Stack,
dann ist sie bei der Art Jazzenzliste ganz hinten,
sonst wäre die nicht oben. Ich habe das deswegen betont,
weil ich das gleich bei allen anderen Knoten andersrum gemacht habe,
aber hier ist es jetzt tatsächlich so,
die Addiazenzliste des Knoten 10, die muss so aussehen 14,
6, weil in anderen Knoten ist die Addiazenzliste so,
dass quasi der linke Knoten in der Darstellung vor dem Rechten kommt.
Also die Addiazenzliste von 6 hier,
das werden wir gleich sehen, die ist 3,
8, das führt dann dazu,
dass die 8 vorne steht
Aber hier, die sechs steht nur deswegen vorne, weil die sechs eben in der Zensliste hinten ist. Wenn wir jetzt die sechs rausnehmen,
so, und jetzt kommen drei und acht,
wenn jetzt eben drei in der ADA-Zensliste vorne steht und dann die drei,
dann die acht, dann nehme ich jetzt die drei,
packe die auf den Stack, nehme die acht,
packe die auf den Stack, dann ist die acht eben oben,
ne, sieht das so aus.
Genau. Ja, und dann halt so weiter,
ne, jetzt nehme ich mir irgendwie die,
jetzt bin ich mit der sechs fertig,
gebe die aus, jetzt nehme ich mir die acht,
packe die Kinder sieben und neun auf den Stack,
neun ist oben, weil neun eben ganz rechts in der Dizenzliste steht,
bin mit der acht fertig und jetzt nehme ich für die neun,
die hat keine Kinder und dann bin ich mit der
fertig,
Dann bin ich also quasi zuerst hier in die Tiefe gegangen,
10, 6, 8, 9, die habe ich jetzt zuerst abgearbeitet.
Normalerweise, wenn ich das gerade,
wenn ich das am Anfang auch richtig gemacht hätte,
dann wäre man zuerst hier irgendwie so abgestiegen, 10,
14, 15, 16 oder irgendwie 10, 6,
2, 3, also so irgendwie in so einem Baum komplett abgestiegen.
Macht ja nichts, dass es ein bisschen anders aussieht hier.
Jetzt nimmt man als nächstes die sieben, ist man mit der
auch fertig. Und jetzt springt man eben durch die,
nimmt man die drei vom Stack, jetzt ist man also hier.
Und geht da in die Tiefe. Drei hat jetzt Kinder
2 und 5, ist fünf ganz vorne auf dem Stack,
drei wird abgearbeitet,
fünf wird abgearbeitet
Wird abgearbeitet. Und dann mit der 14 halt genauso,
wenn nämlich die 14 kommen 12 und 15 auf den Stack.
14 abgearbeitet und so weiter. Und wenn ihr euch das jetzt anguckt im Ausgabe Arry,
es werden quasi die Knoten genau nach Besuchungsreihenfolge,
wenn ich in die Tiefe gehe, ausgegeben.
Man kann das auch so machen,
dass man quasi bei diesem Abstieg, also bei dem,
wo man die Knoten entdeckt, die Dinger noch nicht ausgibt,
sondern erst, wenn man mit ihnen fertig ist.
Also ich sage dann quasi, ich entdecke die Zehen,
ich entdecke die Sechs, ich entdecke die Acht,
ich entdecke die Neuen.
Mit der Neuen bin ich fertig,
weil von da aus gibt es
nichts zu entdecken
Jetzt gebe ich die Neuen aus. Dann gehe ich irgendwie hoch zur Acht,
komme zu sieben, jetzt gebe ich die sieben aus und so.
Dann würde man zumindest entlang eines Teilbaums die Knoten ebenenweise von unten abarbeiten.
Ja, so sieht das aus hier. Es ist komplett das Gleiche,
bis auf den Unterschied, dass S hier eben Stack sein
soll und dass deswegen diese Methoden NQ&DQ ersetzt wurden durch Push & Pop.
Mehr ist nicht passiert. Also am Anfang wird S auf den Stack gepusht,
das irgendwie in die Q zu packen,
dann wird das oberste Element vom Stack genommen,
statt es irgendwie aus der Cue rauszunehmen und hier wird wieder ein Element auf den Stack getan,
statt eben ist aus der Q,
ist in die Q zu tun.
Und der ganze Unterschied im Algorithmus kommt dadurch zustande,
dass die Datenstrukturen Q und Stack eben anders mit ihren Elementen umgehen.
Wenn ihr so ein Stack implementieren würdet und da
auch die Methoden NQ und DQ reinpacken würdet,
dann könntet ihr das einfach komplett einfach im Hintergrund austauschen und habt eine andere Suche im Baum.
Genau, Stack statt Q. So, gleiches Beispiel,
aber jetzt machen wir eine Tiefensuche.
Jetzt fange ich mit dem Knoten 6 an,
mit dem Esther
Und packe alle, oh, Löcher. Wie Schritt habe ich
denn da gemacht? A. Da fehlt doch was. Also,
die Idee war 2, 3 und 8, werden auf den Stack getan.
Zwei ist irgendwie der erste Knoten in der Art der Azenzliste,
3, der zweite, 8, der nächste.
Dann ist 2 ganz hinten im Stack oder ganz unten im Stack,
dann kommt die 3,
dann kommt die 8. Dann würde ich also 6 abarbeiten und
jetzt als nächstes die 8 vom Stack nehmen und eben von
der 8 mir die Kinder angucken.
Das sind 7 und
Packe ich die auf den Stack und gebe die acht aus.
Dann nehme ich die neuen, da gibt es nichts zu tun,
ich gebe die einfach aus. Dann nehme ich die sieben,
die hat als Kind noch die fünf,
packe ich das oben auf den Stack, gebe das aus.
Wichtig ist halt auch hier, ich habe jetzt von sechs
aus die acht entdeckt von acht, die neuen,
dann habe ich als nächstes hier die sieben und dann die fünf entdeckt.
Also gehe ich immer schön in die Tiefen.
Und jetzt erst bin ich bei den Knoten wieder,
die ursprünglich mal die Entfernung eins hatten von dem Startknoten.
Jetzt nehme ich mir die drei entdeckt von der 3,
die 10 und dann nehme ich mir noch die zwei.
Und auch hier, die 10 bearbeite ich vor der zwei,
weil nach sechs kommt die drei,
dann entdecke ich von der 3 die 10,
das ist dann oben auf dem Stack
Über die zwei gelegt wird im Zweck und dann gebe ich die aus.
Fertig. So, da wird es jetzt spannender,
das Ding mit Zusatzinformationen anzureichern. Da kann man jetzt nämlich mit diesem,
was ich eben schon angedeutet habe,
mit diesen Entdeckungs- und Abgearbeitszeiten arbeiten, dass man sagt,
so wann habe ich so einen Knoten entdeckt,
wann sehe ich den das erste Mal, wann habe ich ihn wirklich abgearbeitet?
Was wir machen, so wie eben auch,
Weiß heißt noch nicht besucht, Grau heißt besucht,
aber hat noch unbesuchte Nachbarn,
dann ist er nämlich noch nicht abgearbeitet und schwarz heißt,
ich bin wirklich mit ihm fertig.
Und jetzt gebe ich dem Ding noch zwei Zeitstempel,
D von U, das ist jetzt nicht mehr die Distance,
sondern Discovery, weil ich den Knoten entdeckt habe und F ist,
weil ich den Knoten abgearbeitet habe,
Und beachte immer, wenn die U oder FU gesetzt werden,
wird vorher die Zeit erhöht, dass das quasi,
also es wird jetzt nicht gezählt,
wie oft ich an Knoten entlang gehe oder so,
sondern quasi immer nur, wenn ich DU oder FU setzen will,
erhöhe ich vorher die Zeit um eins.
Weil es mich nicht interessiert,
wie viele Schritte ich irgendwie mache oder so,
sondern mich interessiert quasi nur die Reihenfolge bezüglich Entdeckungs- und Abarbeitungszeiten,
die Reihenfolge, in der die Knoten dann stehen.
Das ist das, was mich interessiert, sehen wir auch
gleich ein Beispiel. Und PU ist weiterhin der Vorgänger,
dass ich eben die Pfade bestimmen kann nachher und so,
dass ich einen ganzen tiefen Suchbaum.
Ups, sieht dann so aus.
Anfang ist fast genauso
Ich mache die, ich setze jeden Knoten auf weiß,
Vorgänger ist immer Nil, Zeit ist am Anfang null.
Und dann sage ich, für jeden Knoten U in VG,
wenn der noch weiß ist, dann rufe ich DFS-Bisit auf auf,
uh, das ist jetzt so ein rekursiver Aufruf gleich.
Und da steckt quasi drin in den Zeilen hier 5 bis 8,
dass ich jetzt so einen Tiefensuchwald bestimme.
Weil über das DFS-Visit kriege ich jetzt alle Knoten,
die von U aus erreichbar sind, sehen wir gleich.
Dann mache ich quasi die Tiefensuche von U aus.
Und wenn dann immer noch Knoten übrig sind,
die weiß sind,
dann nehme ich mir halt in dieser Schleife in Zeile 5
wieder ein davon und fange von dem wieder an und bestimmt noch einen tiefen Suchbaum.
Und am Ende habe ich dann irgendwie mehrere Tiefensuchbäume und
bin fertig
Spannende Teil, DFS Visit. Farbe ist am Anfang grau
von U. Zeit wird um eins erhöht und ich setze die Entdeckungszeit.
Wie gesagt, immer wenn ich DU oder FU setzen will,
erhöhe ich davor die Zeit um eins. So,
jetzt hat DUL-Videos jetzt entdeckt worden und jetzt gucke ich mir
alle Nachbarn an von U,
wenn die noch weiß sind,
dann setze ich halt den Vorgänger von VfU
und rufe rekursiv DFS Visit auf
Das führt also dazu, dass ich jetzt diesen Knoten nicht erst zu Ende abarbeite,
sondern dass ich jetzt erst den nächsten Nachbarn irgendwie aufrufe.
Und bei dem würde ich jetzt auch sagen,
der ist ja noch weiß gewesen,
jetzt gehe ich wieder in diese Routine rein,
also setze ich den auf grau, erhöhe die Zeit um eins und erhöhe dann,
setzt dann seine Entdeckungszeit und immer so weiter.
Irgendwann habe ich hier mal, komme ich hier raus mal zurück,
habe von dem Kind alle Kinder entdeckt oder so,
dann bin ich wieder bei meiner Ursprünge,
bei meinem ursprünglichen Knoten hier und gucke,
habe ich noch einen Nachbarn,
der jetzt
immer noch weiß
Ist. Wenn ja, nehme ich den als nächstes
und rufe das auf dem auch aus und so weiter.
Wenn ich alle meine Nachbarn, wenn alle,
wenn ich diese DFS-Visite-Routine auf alle meine Kinder aufgerufen habe und die alle fertig sind,
dann bin ich auch fertig, dann setze ich mich auf schwarz hier,
erhöhe die Zeit um eins und setze meine Finish-Zeit.
Also mit dem DU und FU ist jetzt gerade so
ein bisschen verwirrend. Im Beispiel wird das, zack,
im Beispiel wird das jetzt schnell ersichtlich.
Wir fangen hier mit dem Knoten an, S,
da nehmen wir jetzt auch einen Gerichteten,
weil das mit gerichteten Grafen
mir Spaß macht
Die Zeit vor dem Strich Balken hier, das ist immer
die Entdeckungszeit und die dahinter ist dann die Finish-Zeit.
Und die dicken Kanten werden gleich diese Vorgängerfunktionen angeben und mir
haben wir ja nicht gesetzt. Wir haben das P-Gesetz,
das D und das F. Wir fangen also mit dem an,
packen A und C auf den Stack.
Leute sind die beide auf dem Stack. Je nachdem,
wie die jetzt in dieser Art Azenz-Liste waren,
fangen wir dann entweder das A ganz oben oder C
ist ganz oben und mit dem machen wir dann weiter.
Das heißt, der würde als nächstes entdeckt werden. Ich bin jetzt,
ich glaube, nach links gegangen,
also das ist quasi die Art Azenz-Liste CA ist,
dann wird zuerst C auf dem Stack getan,
dann auf ins Deck getan,
indem ich A als nächstes runter auf dem Stack
und arbeite mit dem weiter
Dann kriegt A, die Entdeckungszeit 2, ne, wird auch grau.
Jetzt sagt, ah, okay, mein Kind ist irgendwie,
ich habe als Kind nur B oder als Nachbarn, Kind ist als Nachbarn.
Als Nachbarn habe ich B. Also mache ich, ne,
C ist jetzt aktuell noch auf dem Stack,
aber der Knoten A sagt jetzt, oh,
mein Nachbar ist B, ich packe den ganz oben auf dem Stack.
Das heißt, als nächstes bin ich bei B. Den
kriegt B diese Entdeckungszeit 3. Und jetzt passiert was,
können wir jetzt schon mal kurz diskutieren.
Man kann jetzt mit diesen Kanten arbeiten.
Man kann jetzt hier, der sagt, ja,
ich habe weiterhin Nachbarn, den ich sehen kann über
diese Kante hier
Nämlich den Knoten S. Und jetzt kann man gucken, welche Farbe es hat.
Wenn es weiß ist, dann würde ich da ja hingehen.
Also vorher war hier von A ausgesehen B weiß,
das ist so der Normalfall, dann sage ich,
okay, da gehe ich hin.
Wenn der grau ist, so wie hier,
dann weiß ich im Grunde genommen, ich komme von diesem Knoten.
Also wenn der grau ist, sagt mir das,
es gibt einen Pfad von diesem grauen Knoten zu mir.
Sonst wäre er nämlich schon abgearbeitet. Das bedeutet,
wenn es einen Pfad gibt,
von da zu mir und von mir wieder eine Kante zu dem,
was habe ich da im Kreis
Sieht man ihr ja auch, ne? S-A-B-S wäre ein Kreis
. Das heißt, über solche Kanten, sogenannte Rückwärtskanten,
weil ich quasi im Baum wieder nach oben gehen würde, nach zurückgehen würde.
Damit kann ich feststellen, ob es Kreise in meinem gerichteten Grafen gibt.
Nennt man B-Kanten für Backwards, glaube ich. So,
dann stelle ich aber fest, okay,
ich habe keine Kinder, also zurück in den eigentlichen Algorithmus,
ohne jetzt mit Kanten zu spielen.
Ich stelle fest, ich habe keine Kinder.
Ich bin also fertig. Ich komme aus dieser Vorschleife raus,
in der ich alle Nachbarn besuche und sage, okay,
dann Zeit wieder um einen erhöhen, Finish-Zeit setzen.
Dann kriegt der also die Finish-Zeit 4
und wird schwarz
Bei mir ist grün schwarz. Also,
der ist jetzt fertig. Jetzt gehen wir zurück,
ne, also sind alle Nachbarn von A bearbeitet,
das heißt A ist jetzt da, dass er sagt,
meine Vorschleife ist zu Ende abgearbeitet.
Ich werde schwarz, ich setze meine Finish-Zeit ein,
ich setze die Zeit ein höher und das wird meine Finish-Zeit.
Das heißt, der, ihr kriegt die Finish-Zeit 5.
Was passiert jetzt? Bitte? Genau, C ist
noch auf dem Stack und wird jetzt als nächstes entdeckt.
Das heißt, es wird jetzt nicht irgendwie S
Es ist als abgearbeitet bezeichnet und kriegt den Wert 6,
sondern C wird entdeckt und kriegt diese Zeit sechs als Entdeckungszeit.
Und dann stellt C hier fest, es gibt eine Kante
zu so einem schwarzen Knoten. Ja,
das sind dann sogenannte Crossing-Kanten, weil man quasi,
wenn euch das jetzt in dem Baum vorstellt,
dann habt ihr quasi hier diesen Pfad S-A-B und ihr habt diesen Pfad zu C. Ja,
und dann gibt es von zehn eine Kante in diesen anderen Ast.
Deswegen so Crossing-Kanten,
ihr geht quasi von einem Ast im Baum einfach quer rüber
zum anderen
Will man manchmal, kann man auch für Dinge benutzen.
Dann ist der fertig, Zeit wieder um einen erhöhen,
kriegt er den Wett7. Jetzt ist S auch fertig und kriegt den Wert 8. Alles gut.
Und jetzt war das in dem Algorithmus ja so,
dass jetzt gesagt wurde,
wenn es jetzt immer noch weiße Knoten gibt, dann starte ich,
dann nehme ich mir einen davon und mache bei dem wieder das Gleiche.
In dem Beispiel habe ich das jetzt so gemacht,
damit das irgendwie hübsch nochmal aussieht,
dass ich jetzt mit E weitermache,
wenn wir jetzt mit D weitermachen würde,
dann würde man
noch zwei einzelne Bäume finden
Von dem aus würde man jetzt sagen, okay,
ich entdecke ihn mit der Zeit neun,
dann entdecke ich den mit der Zeit zehn,
bin mit dem fertig,
mit der Zeit elf und mit ihm bin ich dann fertig mit der Zeit zwölf, ne?
Zehn abgearbeitet, da wieder eine Crossing-Kante und zwölf.
Da ist es quasi sogar eine noch schlimmere Crossing-Kante,
weil man weiß, dass ich in einen anderen Baum springen würde.
Hier weiß ich, ich springe von einem Ast des Baums
in einen anderen. Hier weiß ich, ich springe in
einen ganz anderen Baum.
Kann man sich
mal kurz überlegen
Bitte? Ja, man kann das rauslesen. Ich frage mich, ich... Ja,
ich muss quasi hier die Wurzel bestimmen und dann weiß ich,
in welchem Intervall ich bin und dann kann ich hier rauslesen,
dass ich eine Crossing-Kante habe.
Zu den Intervallen kommen wir auch gleich nochmal, aber man kann schon sehen,
dass irgendwie der Teilbaum hier sich in einem bestimmten Intervall bewegt.
Das ist das Intervall 1 bis 8 und dieser Baum hier bewegt sich im Intervall 9 bis 12.
Also es gibt irgendwelche Zusammenhänge zwischen den einzelnen Knoten. Man kann auch sehen,
hier ein Kind, also ein Kind von dem hier,
Der Knoten A, eine Knoten B,
B ist ein Kind von A und diese sowohl,
also dieses Intervall, was durch ihr Entdeckungs- und Finishing-Zeit da gegeben ist,
dieses 3, 4, das ist ein Teilintervall des Intervalls 2,
5, 4. Weil B eben Kind ist.
Während das hier sechs, sieben, das ist kein Teilintervall von dem,
sondern die beiden Intervalle sind es jung, also zwei,
fünf und sechs, sieben sind irgendwie das Jungt.
Also sollen die eben dann nicht in so einer Kindsbeziehung
irgendwie zueinander stehen.
Man kann bei der Tiefensuche die Kanten klassifizieren, genau,
das war das,
was ich eben auch schon so zwischendurch erzählt habe,
je nachdem, welche Farbe eben der Knoten V hat,
wenn ich den über so eine Kante, UV,
das erste Mal sehe.
Also U habe ich schon, ich bin gerade dabei,
U zu bearbeiten. Ich sehe V,
wenn V weiß ist, dann wird es eben eine Baumkante.
Wenn V grau ist, dann wird es diese Rückwärtskante.
Das war dieser Fall, wo wir von dem oberen Knoten
eben zum Startknoten irgendwie kommen konnten.
Und wenn V schon schwarz ist, dann ist es
entweder eine Vorwärts- oder eine Querkante.
Vorwärtskanten hatten wir eben gar nicht, können auch auftreten.
Also quasi im Baum dann kannten,
die irgendwie nach vorne springen würden
Das kann dadurch passieren,
wenn ihr quasi drei Knoten habt, A, B,
C und ihr entdeckt jetzt von A aus zu SB und dann C,
dann ist C jetzt abgearbeitet, dann ist B abgearbeitet und seid bei A.
Und wenn A jetzt noch eine Kante zu C hätte,
dann wäre das so eine Vorwärtskante.
Weil man dann eben auch sagen würde, oh,
ich könnte den jetzt nochmal entdecken,
aber ich habe den schon entdeckt,
so.
Ja, die Knoten, also die Zahlen,
die bei den Knoten A und C stehen.
Nicht das C jetzt von der Kante,
aber wenn du dir jetzt die Zahlen an,
also mit Intervall ist quasi gemeint,
du guckst ja diese Statue und diese Finishing-Zeit an und das
ist ja ein Intervall in den natürlichen Zahlen oder so.
Und bei A ist das Intervall ja 2,5. Bei dem anderen
ist das Intervall 6,7. Und diese beiden Intervalle, die haben nichts gemeinsam.
Deswegen das jungt. Während so Intervalle wie das bei A und B,
da sieht man halt dieses Intervall von B,
die 3,4, das ist enthalten in dem anderen Intervall.
Und wenn man einen Knoten hat,
dessen Intervall quasi enthalten ist in dem Intervall des anderen Knoten,
dann ist dieser Knotenkind.
Und wenn die das jungt sind, dann sind die irgendwie
auf unterschiedlichen Faden
Das kann man nachher halt so für so ein paar Anwendungssachen ganz cool benutzen.
So. Genau, und dann eben diese besonderen Kanten,
ich glaube, das habe ich alles erzählt,
ne?
Tiefensuche ist korrekt. Okay. Müsste man sich überlegen,
was will man damit eigentlich ausdrücken? Da müsste man sowas sagen,
wie bei der Tiefensuche besuche ich alle Knoten und ich besuche ja
auch in einer bestimmten Reihenfolge und dann kann man eben zeigen,
dass das irgendwie korrekt ist.
Laufzeit ist wieder ein V plus E, kann man sich
genauso schnell überlegen, wie bei der Breitensuche auch.
Im Grunde genommen werden ja einfach nur die Q-Operationen durch Stack-Operationen ausgetauscht.
Also kann jetzt die Laufzeit nicht sonderlich viel anders werden,
wenn ich vorher argumentiert habe,
ich habe O von V4 eine Q-Operation,
dann habe ich jetzt eben O von V4 eine Stack-Operation oder alles andere ist genauso.
Also wird das wieder eine V plus E sein
Auch wieder, wenn das denn als Addiazenzliste gegeben ist bei
dem anderen, braucht man ein bisschen länger.
Joa. Zusammenfassung, Breitensuche nutzen, eine Q,
tiefen Suche ins Deck. Im Kormen hier gibt es so
eine Variante von der Tiefensuche, da macht er das ohne Stack.
Ich bin mir gerade gar nicht sicher, vielleicht hat er
auch beide drin stehen oder das eine ist eine Aufgabe oder so.
Er hat auf jeden Fall im Haupttext diese Variante ohne
Stack stehen
Ach genau, dafür arbeitet Sigrico anders. Genau,
er macht das ohne Stack, aber rekursiv und mit Zeitstempeln,
so wie wir das auch eben in dem Source-Code hatten.
Jetzt kann man sich drüber streiten, bei rekursiven Aufrufen wird
intern irgendwie ein Stack benutzt, um das zu realisieren.
Also ist da auch irgendwie ein Stack drin,
aber jetzt von der Ausführung des eigentlichen Algorithmuses kommt er ohne Stack
aus und man kann das und man möchte noch so aufdröseln,
dass man dann halt auch ohne diese rekursiven Aufrufe von DFS Visit auskommt und einfach ein iteratives Verfahren hat.
Genau. Dann beide laufen in Täter von V plus e,
wenn der Graf dann als Atjazenzlisten gegeben ist,
Breitensuche macht man meistens so,
dass ich da nur einen Startknoten nehme und dann eben alles besuche,
zumindest bei einem ungerichteten Grafen geht das ja
Und Tiefensuche, die benutzen wir am meisten in unseren Tiefensuchwald
zu bestimmen und dann eben auch aufgerichteten Grafen zu arbeiten.
Ja, das dazu fragen.
Fragen zur Tiefensuche oder zur breiten Suche.
Wenn du mit deinem Navigationsgerät versuchst, durch die Stadt zu fahren.
Wahrscheinlich weder noch, sondern ein kürzester Pfadalgorithmus.
Weil da hast du ja gerade so Sachen wie irgendwie bestimmte
Zeiten vielleicht noch, Entfernungen und so weiter.
Und dann musst du mit irgendwas anderem arbeiten.
Da sind zwar solche Sachen so Ideengeber für,
aber da würdest du einen kürzen Pfadalgorithmus benutzen, einen Dicstraw oder sowas.
Für alle Knoten die kürzesten Pfade dahin bestimmen und damit dann irgendwie arbeiten.
Genau, weil du da nämlich genau das hattest,
was du vorhin meintest, mit Gewichten.
Sonst noch
Überleitung zum neuen Thema gleich. Wenn ihr, wer von euch
benutzt To-Dos, wer von euch benutzt To-Dos, alle To-Do-Verwaltungs-Software?
Eine To-Do-Verwaltungs-Software? Ihr guckt mich alles an,
als ob ihr gar nicht wisst, wovon ich rede.
Ihr habt doch bestimmt unterschiedliche Dinge zu tun, oder?
Und sowas muss man
manchmal verwalten
To-do. Bitte? Nochmal? Ja. Ich meine,
ich benutze Asky-Files, das zählt auch. Das ist total okay
. Nee, ich benutze dir keinen To-do-Verwaltungs-Dool, To-do-Verwaltungstool.
Nee, ihr kommt alle so aus? Oder benutzt ihr irgendwie
einen Notizblock? So, da schreibt man sich das so
auf, so. In 22 Tagen ist Weihnachten Geschenke kaufen.
Jetzt nehmen wir mal an, ihr seid irgendwie,
ihr habt viele Dinge, die ihr irgendwie kombinieren müsst.
Ihr habt irgendwie, was habt ihr denn so alles?
Ihr habt eine Freundin, ihr habt,
ihr müsst kochen am Abend, also müsst ihr noch einkaufen gehen.
Die Wäsche muss auch dringend mal wieder gewaschen werden.
Jetzt gibt es vielleicht so Abhängigkeiten. Heute Abend denkt ihr so,
geil, so ich gehe mit meiner Freundin aus.
Jetzt wäre es irgendwie cool, wenn ihr vorher die Wäsche gewaschen habt.
Also nicht nur vorher gewaschen, sondern auch zeitlich so doll vorher,
dass ihr wisst, ihr könnt sie dann auch noch anziehen,
wenn ihr zum Date geht.
Nicht, dass ihr irgendwie wie so ein nasser Sack da
irgendwie zu diesem Date erscheint. Dann wollt ihr vielleicht,
ist das Date nicht im Restaurant, sondern ihr habt gesagt,
oh cool, ich lade sie ein.
Also müsst ihr auch vorher kochen. Jetzt stellt ihr fest,
okay, vor dem Kochen muss ich irgendwie noch eingekauft haben
Dann stell dir fest, das ist alles total cool,
aber meine Mutter hat ja übermorgen Geburtstag.
Ich muss auch noch ein Geschenk für sie kaufen.
Ihr merkt schon so, die To-dos sammeln sich. So,
was ich jetzt gerne hätte, wäre eine Software, die folgendes tut.
Ich gebe meine ganzen To-dos ein. Ich sage so irgendwie,
ja, ich muss Wäsche waschen, ich muss die Wette trocknen,
ich muss kochen, ich muss einkaufen, bla,
bla, bla, bla.
Ich will nochmal zum Friseur gehen und so weiter und so weiter.
Dann gebe ich noch ein bisschen Abhängigkeiten ein, dass ich
irgendwie sage, Waschen vortrocknen. Wenn ihr ganz cool seid,
schmeißt ihr noch ein bisschen Machine-Learning-Algorithmen drauf, die euch selbstständig sagen,
dass man normalerweise 90 Prozent der Leute, die dieses Tool benutzen,
waschen ihre Wäsche, bevor sie sie trocknen oder so,
dann macht das das Tool,
das fällt automatisch
So, jetzt habt ihr die ganzen To-dos drin und ihr habt die Abhängigkeiten drin.
Jetzt möchte ich gerne, also ich weiß nicht,
wie ihr das macht, ich mache das normalerweise so,
ich habe das dann irgendwie in meinem Aski-File drin.
Aski ist ja auch super, ich kann das nicht mal
farblich hervorheben. Das heißt,
ich arbeite dann irgendwie so mit Ausrufezeichen und Sternchen und so,
bringe die irgendwie in eine Reihenfolge und dann versuche ich das irgendwie abzuarbeiten, völlig behämmert.
Das ist noch so richtig aus dem letzten Jahrtausend.
Es wäre ja cool, wenn ich einen Knopf drücken kann
und das Tool sagt mir dann, mach es so.
Also die völlige Befreiung vom Sortieren sozusagen.
Wie kann man
sowas machen
Habt ihr eine Idee? Wenn ich euch jetzt zwei Tasks gebe,
ist leicht, so zwei Tasks und eine Abhängigkeit,
sagt ihr, naja, okay.
Okay, geschenkt. Bei dreien, einfach nur zu sortieren,
wird nicht reichen. Beim Sortieren brauche ich eine Ordnung auf
allen Elementen. Die habe ich hier ja vielleicht gar nicht.
Ich weiß ja vielleicht nur sowas wie Task A,
muss ich vor Task B machen.
Task C muss ich auch vor Task B machen.
Aber A und C stehen vielleicht in gar keinem Verhältnis zueinander.
Das kann man natürlich sagen, ich kann die sortieren oder
irgendwie die beiden kann ich beliebig machen oder so.
Ja, sehr schön, wenn ich schon sage,
wir haben so irgendwie bestimmte Voraussetzungen,
da kann man gut als Graf modellieren zumindest.
Vielleicht noch nicht als Baum, aber als Graf,
dass man irgendwie weiß, okay,
die und die und die und die.
Alle Items sind ein Knoten. Ich weiß nicht.
Was passiert denn, wenn wir Kreise drin haben?
Ja, dann haben wir keinen Baum mehr.
Was wäre denn das für ein To-Do, wenn du Abhängigkeiten
drin hättest? Was wäre das für ein To-Do,
wenn du einen Kreis drin hättest
Was? Ja, ein ewiges To-do. Was? Waschen,
trockenen, tragen, waschen, trockenen, tragen, waschen,
trockenen, tragen, ja, was kann man machen?
Jetzt ist es so ein bisschen so zu sagen,
dass das Tragen der Klamotten, und das ist eine Vorbedingung fürs Waschen,
das Marktstimmen, ein bisschen grenzwertig.
Also normalerweise will man keine Kreisabhängigkeit drin haben in seinen To-dos, ne?
Ist zwar vielleicht so, dass man schon weiß,
ja, wenn ich es erledigt habe,
muss ich es irgendwie nächste Woche wieder machen oder so,
aber dann schränkt man sich halt irgendwie ein.
Okay, jetzt haben wir es irgendwie als Graf modelliert,
so alle Items sind irgendwie
ein Knoten
Und die Kanten zwischen den Knoten sind das,
was ich irgendwie als Abhängigkeiten weiß. Wie könnte ich jetzt
damit arbeiten? Das wüsste ich jetzt so, ne?
Weiß ich zum Beispiel, was weiß ich denn?
Welche Knoten sollte ich zum Beispiel zuerst bearbeiten? Das kann man
relativ gut rauslesen. Das Setting ist klar, ne?
Ich habe alle Knoten und ich habe Kanten zwischen den Knoten,
die mir die Abhängigkeiten sagen.
Also wenn ich eine Kante von A zu B habe,
eine gerichtete, dann heißt es,
ich muss A vor B erledigt haben.
Welche Items sollte ich
zuerst erledigen
Welche macht die meisten auf jeden Fall? Ja. Jetzt hat er gesagt,
welcher hat die meisten ausgehende, das korrigiere mich,
weil ich es falsch zusammenfasse, ich nehme den Knoten,
also ich gucke mir erstmal alle Knoten an,
wer hat die meisten ausgehenden Kanten und den Knoten mit den meisten ausgehenden Kanten,
den mache ich zuerst,
richtig?
Das wäre ja vielleicht eine ganz coole Heuristik oder so.
Das knallt noch an der Stelle, warum knallt das?
Können wir ja eine Kante haben, die auf ist.
Genau, der könnte ja eine Vorbedingung haben,
dann ist das doof.
Welche Sachen bearbeite ich zuerst
Genau, die ohne Vorbedingungen. Also ich würde jetzt einmal
über den Grafen vielleicht drüber lesen, würde sagen,
okay, welche Knoten haben gar keine Vorbedingungen?
Die mache ich zuerst. Dann habe ich irgendwie eine bestimmte Anzahl von Knoten erledigt.
Was mache ich jetzt? Jetzt freue ich mich. Okay,
jetzt weiß ich schon mal, ich bin beschäftigt für heute.
Mehr schaffe ich heute nicht. Naja, das wäre doch nicht
so gut. Da wäre ich noch nicht so zufrieden mit
meinem Tool. Ja, dann bearbeitet man mehr Nachbarn.
Ja genau, jetzt bearbeitet man der Nachbarn.
Aber welche? Ja, fast. Ich glaube,
du meinst das Richtige, aber ich bearbeite ja nicht einfach
irgendwelche Nachbarn
Alle. Den Nachbarn von einem Knoten, der nur,
das ist ja knotenüber innerlich. Genau, das meinst
du bestimmt, weil alles andere würde keinen Sinn machen.
Genau, man nimmt jetzt, jetzt guckt man sich an,
welche Sachen habe ich alle bearbeitet. Was man machen könnte,
wenn man schmeißt die jetzt raus aus dem Grafen.
Dann sind die weg. Dann muss wieder einer entstehen,
der keine Vorgänger mehr hat, so, ne?
Und dann mache ich mit dem weiter. Na, mit Tiefensuche. Wie kann ich das,
also das ist jetzt so ein Verfahren,
das Verfahren ist deswegen doof, oder was heißt doof,
das Verfahren funktioniert, aber das klingt jetzt so wie,
Ich gucke mir alle Knoten an, die Knoten,
die keine Vorbedingungen haben, die bearbeite ich.
Mir schon mal ein O von V. Dann schmeiße ich die raus,
mit denen ich jetzt fertig bin. Als nächstes gehe ich
über alle Knoten rüber und nehme mir wieder die und so weiter.
Dann habe ich irgendwie so ein Verfahren, das ist so ein V-Quadrat oder so.
Das mag für die meisten To-dos irgendwie reichen,
weil die wenigsten To-dos wahrscheinlich aus einer Million Sachen bestehen oder so.
Ich hoffe, keiner von euch hat eine Million Items auf seiner Liste,
aber man kann es schneller hinkriegen mit einer Tiefensuche.
Wenn ich eine Tiefensuche mache auf dem,
ich habe ja jetzt ganz viele Items,
die ich erledigen will, ich mache da eine Tiefensuche drauf.
Ja, da hat er dann, jetzt kriegt man Infos über
Man kriegt doch diese Distance-Zeiten und die Finishing-Zeiten.
Wie könnt ihr denn die benutzen? Was schön ist denn,
dass das nur ein O von V plus E,
das ist nicht ganz so doof.
Würde ich das benutzen. Ich bearbeite die, ich muss selbst
gerade nachdenken. Ja, okay, ich weiß wieder.
Das ist ein bisschen fies ohne das Bild, ne?
Der wäre jetzt nicht ganz so cool,
weil es diese Kante von B zu S gibt,
da hätte ich einen Kreis, also nehmen wir mal an,
die ist weg
Dann... Und die Kante von E zu A,
wahrscheinlich auch noch, ne? Die sollte vielleicht auch noch weg.
Nehmen wir mal einfach nur den oberen, die oberen vier Knoten,
das reicht, um die Idee zu sehen, glaube ich,
und streichen die Kante von B zu S weg.
Ja, ich glaube, das ist nicht so schlimm.
Ja. Ja, das würde einfach nur mit,
ja, was würde das bedeuten? Ja. Ja,
man kann durch diese, diese Zeitangaben,
so unabhängige Aufgaben,
die Aufgaben kann ich lösen
Oder wie, wo ist das, was wir aufeinander machen.
Ja, aber wie? Also du kannst das da rauslesen tatsächlich.
Ja, das, ja, wir können mal zwei Jahre 5 auf.
Und er knopft sich da, der fängt bei 690.000.
Ja. Ja, das ist vielleicht das Jugendzusatz.
Ja, ähm, ja. Ich bin auch nicht zufrieden
, nee. Das ist ja noch kein Algorithmus.
Du sagst jetzt gerade nur, die sind es jung,
sag ich so, ja, die sind es jugend uns.
Ich hatte so die Nachbarn vielleicht. Ja, nee.
Aber fast
Ich brauche eigentlich weniger. Und wenn ihr euch das anguckt,
wenn ihr euch den oberen Teil da anguckt,
mit welchen Knoten würdet ihr anfangen?
Wenn ihr den, der Baum kommt raus,
nehmen wir mal an, der Baum kommt raus, ne?
Und jetzt kann man rauslesen, mit welchem Knoten man anfangen will.
Ich meine, man kann es jetzt gerade auch sehen, ne?
Man würde mit S anfangen, weil S hat keine Vorbedingung, ne?
Also fange ich mit S an. Wenn ihr euch das anguckt,
was unterscheidet S von den anderen Knoten bezüglich dieser Zahlen?
Weißt du? Was? Ja, das hilft uns nicht so richtig,
weil dann würde A und B, dann würde A auch sagen,
ich habe irgendwie mehr als B oder so,
das reicht noch nicht,
kann man
einfacher machen
Das kann man auch sehen. Differenz ist am größten auch sehr schön,
weiß ich nicht, ob man das benutzen kann.
Müsste ich jetzt bestimmt länger drüber nachdenken, als ich gerade habe.
Na, tschö. Es hat die Anfangszeit 1. Ja,
nimm mal die andere Zeit.
Es hat die Endzeit 8. Sortiert die Knoten mal nach absteigender Endzeit.
Was kommt da raus? SCAB. Das sieht gut aus
. Wenn ihr das nach aufsteigender sortiert,
dann kriegt ihr
Also wenn du die Anfangszeit nimmst, ne,
und jetzt nach Anfangszeit sortierst,
dann kriegst du raus S, hat die Anfangszeit 1,
A, hat die Anfangszeit 2, B,
hat die Anfangszeit 3 und dann C.
Das ist doof, weil ich muss C vor B überarbeitet haben.
Ja? Nicht? Ja. Naja, wegen dieser
gestricheten C-Kante da. Ja, ist ein bisschen fies.
Ich wollte nur die B-Kante rausschmeißen, nicht die andere.
Also diese gestrichelte C-Kante ist noch da.
Aber wenn ihr nach absteigenden Finishing-Zeiten sortiert, dann funktioniert es.
Zumindest kann man sich das Bild angucken und sich irgendwie denken,
hm, vielleicht könnte das mit den absteigenden Finishing-Zeiten funktionieren
Und gleich werden wir beweisen, dass das funktioniert.
Also gleich machen wir einmal noch mal kurz im Detail das Verfahren.
Die Idee wisst ihr jetzt schon, man macht eine Tiefensuche,
sortiert die Knoten nach absteigender Finishing-Zeit und dann kriegt man eine,
man nennt das eine topologische Sortierung.
Und dann wollen wir einmal beweisen, warum das funktioniert.
Viertelstunde Pause? Ja. Viertelstunde Pause,
du bist Viertel vor und dann machen wir den Beweis.