So, wir haben ein bisschen technische Probleme.
Oh, oh, oh. Seid ihr alle soweit?
So langsam müsstet ihr euch doch jetzt so über die Vorlesungsfreizeit
so ausgetauscht haben, dann könnten wir doch anfangen.
Sehr gut. Wir haben ein bisschen technische Probleme,
dass Video, also normalerweise gibt es ja,
normalerweise werden die Folien direkt zu Kim gespeist und das klappt heute leider nicht so richtig.
Deswegen filmt da jetzt einfach die Folien ab. Da ist dann
die Qualität bei dem Video natürlich nachher nicht ganz so gut,
wie wenn man das sonst so machen würde,
wie wir das bei FG1 gemacht haben.
Wir hoffen, dass wir das zum nächsten Mal irgendwie hinkriegen.
Livestream weiß ich gerade gar nicht, Kim,
machen wir Livestream
Ja, nächstes Mal. Ab nächstes Mal machen wir einen Livestream.
Aber der startet dann immer erst um zehn, ne?
Also so von neun bis zehn ist Präsenzzeit und danach startet der Livestream.
Genau, also nächstes Mal live zu ihm, Link,
tue ich auf die Webseite. Genau,
die Folien kommen ganz normal wieder auf Lecture to Go,
da kommt der Link dann auch auf die Webseite,
Webseite ist wieder unter Informatik, TGI und so weiter.
Also Informatik, TGI, dann da irgendwie Leere und dann
könnt ihr euch da zur A&D durchklickern. Da gibt es eine Seite,
so wie bei FGI1, auch einmal für die Vorlesung,
da lege ich dann immer die Folien und sowas ab und einmal für den Übungsgruppenbetrieb,
da lege ich dann irgendwie die Aufgabenzellung,
die Musterlösung und so ab
Genau. Wer hat letztes Semester bei mir FG1 gehört?
Wer hat letztes Semester nicht FG1 von mir gehört?
Jetzt haben wir uns alle einmal bewegt. Jetzt sind wir
hoffentlich alle einmal wach. Dann können wir ja loslegen.
Modul. Heute Algorithmen und Datenstrukturen. Ich bin für die,
die jetzt noch nichts von mir gehört haben,
ich bin Frank Heidmann, ich arbeite bei der Arbeitsgruppe TGI.
Und das ist ja so ein 3-Plus-1-Modul, also 3-Stunden-Vorlesung,
eine Stunde Übungsgruppe. Und erstmal kurz, ich zum Organisatorenzeit
. Gleich noch war es erstmal so ganz grundlegend,
worum geht es überhaupt bei Algorithmen und Datenstrukturen
Als irgendwie, es geht um Algorithmen und es geht um Datenstrukturen,
okay, Algorithmen, irgendwie etwas, womit wir mechanisch,
also sprich durch eines vom Computer, versuchen, ein Problem zu lösen.
Dann ist der erste Schritt normalerweise, ich habe irgendwie ein
mehr oder weniger genau definiertes Problem in der richtigen Welt.
Das muss ich jetzt erstmal auf irgendwas mappen,
sodass ich das irgendwie mit dem Computer ausdrücken kann.
Dafür helfen uns Datenstrukturen, irgendwie Daten,
die dann eben noch eine bestimmte Struktur haben.
Einfachstes Beispiel in Array, da habt ihr ja irgendwie jede Menge Zahlen.
Zum Beispiel können wir auch irgendwas anderes haben,
aber bei einem Falldurchstand irgendwie zahlen und dann werden die
eben noch in einer bestimmten Struktur abgelegt,
sodass man mit bestimmten Methoden da darauf Zugriff hat.
Beim Array hat man irgendwie beliebigen Zugriff auf die einzelnen Elemente,
man muss aber den Index kennen
Bei anderen Datenstrukturen, Bäumen und sowas hat man vielleicht am Anfang
nur Zugriff auf das Wurzel-Element und muss dann durch den Baum wandern,
um ein bestimmtes Element zu kommen.
Aber die Idee ist halt bei einer Datenstruktur,
ich habe jede Menge Daten, lege die auf eine bestimmte
Art und Weise ab und habe dann eben durch die Methoden Zugriff da drauf.
Und die Algorithmen arbeiten dann mit diesen Datenstrukturen, um eben irgendwie ein Problem zu lösen.
Und das, was wir machen wollen in dieser Vorlesung,
ist uns einerseits für bestimmte Probleme, Lösungen,
die andere Leute schon hatten, anzugucken, zu versuchen,
die zu verstehen und die zu bewerten.
Und andererseits eben dann für neue Probleme,
Selbstalgorithmen zu entwickeln, halt so mit den Techniken,
die wir dann vielleicht uns von den anderen irgendwie abgucken,
so Ready-Verfahren,
die weit in Konka-Verfahren und so,
wie man da
schon mal was sagt
Und das wollen wir machen. Warum machen wir das?
Also was nützt das? Der erste Punkt hier,
Spaß. Mal gucken. Also hoffentlich macht es Spaß.
Algorithmik ist eigentlich so eine Kerndisziplin von der Informatikausbildung,
weil selbst wenn man jetzt vielleicht später im Betrieb nicht selbst spezifische Algorithmen entwickelt,
ruft man meistens irgendwelche Library-Funktionen auf,
wo dann wieder Algorithmen dahinterstehen und dann muss man zumindest bewerten können,
was das jetzt ist, ob das gut ist oder nicht.
Also wenn ja irgendwie ein Sortieralgorithmus aufruft und in der Library steht nur drin,
ja, das ist ein Bubbleshord oder so,
da ist ein Quicksort,
dann sollte die irgendwie in der Lage sein zu verstehen,
was damit wohl gemeint ist.
Also sollte das
irgendwie einordnen können
Und die eigentlichen Ziele grob abschätzen, was überhaupt möglich ist,
das hatten wir schon in FG1, Thema Unentscheidbarkeit, Entscheidbarkeit und so,
dass man vielleicht sogar schon auf den ersten Blick irgendwie relativ schnell sagen kann,
oh, das weiß ich schon,
das geht gar nicht, das muss ich irgendwie einschränken.
Also was ist überhaupt möglich, dann,
was ist aus praktischer Sicht möglich, sprich, wie teuer kann was werden,
teuer wird bei uns immer sein, Zeit und Platzbedarf,
später vielleicht auch in der Vorlesung hier, glaube ich,
nicht mehr, aber später vielleicht auch sowas wie Bedarf an Prozessoren.
Also wenn ich dann irgendwie sage, ich brauche dafür eine ganze Serverfarm,
um das Problem effizient zu lösen, habe ich aber nicht,
dann kann ich das halt wieder praktisch nicht lösen.
Und Zeit und Platzbedarf eben auch, wenn etwas zwar theoretisch lösbar ist,
ich dafür aber Jetzt kommen immer so Beispiele wie irgendwie,
länger braucht er als das Universum existiert oder so,
ja okay, das ist jetzt sehr extrem,
aber es reicht ja vielleicht auch schon,
wenn ihr bei einer Google-Suchanfrage immer eine Minute auf die Antwort warten müsstet,
dann wäre die Seite wahrscheinlich nicht so populär,
wie sie ist.
Also wie teuert, was ist es auch immer ein bisschen
davon abhängig, was man gerade benutzen will? Genau,
dann Lösungsvorschläge und deren Kosten verstehen, das war das,
was ich meinte und wir gucken uns Probleme und Lösungen an,
die schon existieren und wir wollen Lösungen selbst erarbeiten.
Und das, was quasi über einem so drüber steht,
ist dieses Thema Abstrahieren,
weil man eben ein Problem aus der realen Welt erstmal irgendwie so umformulieren muss,
dass man das überhaupt in ein Computer,
in einem Computerprogramm bearbeiten kann
Also das wollen wir machen, um organisatorisch einmal zur Vorlesung,
höher seiner Archemie, da sitzen wir gerade alle.
Und weil drei Stunden Vorlesung irgendwie für alle, glaube ich,
ziemlich strapazierend ist, wollte ich das ein bisschen ausblitten.
Die ersten anderthalb Stunden mache ich eine Vorlesung. Da gibt es auch immer
eine Lecture-to-go-Aufzeichnung zu und ab nächsten Mal dann auch dem Livestream.
Dann mache ich irgendwie eine Viertelstunde Pause und dann soll es
nochmal von 11 bis 11.45 Uhr will ich dann den Stoff,
den wir in den ersten anderthalb Stunden gemacht haben,
nochmal wiederholen, vielleicht mit kleinen Übungen anreichern,
bei bestimmten Aspekten vertiefen
Da gibt es dann keine Elektro-To-Go-Aufzeichnung mehr, weil ich da möchte, dass wir irgendwie ein bisschen miteinander interagieren und ihr dann eben irgendwie dabei nicht aufgezeichnet werden sollen müsst, wird. Genau,
dann bei der Vorlesung kennt ihr auch schon das FDI-1,
ich arbeite immer so mit irgendwie Boxen,
die gelben Boxen sind quasi immer die,
was normal wichtig ist, die roten Boxen ist das,
was irgendwie ganz wichtig ist,
was man auf jeden Fall irgendwie mitnehmen sollte und blaue Boxen sind mehr so für Interessierte,
so irgendwie Exkurse oder Vertiefung,
die jetzt irgendwie nicht jeder aus dem Modul mitnehmen muss,
aber für die,
die schon wissen,
irgendwie da will ich mich dann spezialisieren oder ich habe
noch viel Zeit übrig in der Woche,
dann könnt ihr da reingucken
Genau. Buch zur Vorlesung kommen,
also Callment Introduction to Algorithms, gibt es auch auf Deutsch
Einführung in die Algorithmik. Ja, gibt es,
ich glaube, 40, 50 Mal in der Bibliothek,
wird also nicht für alle reichen, kann man sich aber auch kaufen.
Das ist ein relativ dickes Buch. Wissen da drin wird auch eher nicht,
obsulid, also kann man das eigentlich ganz gut benutzen.
Ihr könnt auch ein beliebiges anderes Algorithmen im Buch nehmen,
also wenn euch irgendwie, wenn ihr sagt so,
der Schreibstil von dem Corman und seinen Kollegen gefällt mir nicht,
den könnt ihr auch mal in der Bibliothek gucken,
was noch so an Algorithmenbüchern gibt.
Der Stoff ist relativ standardisiert
Dass ihr die Sachen, die ich mache,
die werdet ihr auch in anderen Algorithmen Büchern finden,
vielleicht mal irgendwie ein bestimmtes Kapitel nicht oder so,
aber dann liest man das eben nochmal speziell irgendwo nach.
Das zur Vorlesung, zu den Übungsgruppen,
die beginnen schon heute, also heute Morgen und übermorgen,
Mittwoch, Donnerstag, Freitag, sind immer die Übungsgruppen,
die Übungsgruppen sind alle zwei Wochen und dann zweistündig.
Das ist ein 3-plus-1-Modul, also gibt es eigentlich nur eine SWS-Übungsgruppe,
hören die alle zwei Wochen und dann sind die alle zwei Wochen
zweistündig und die sind, für die die DDB haben,
immer irgendwie ein Wechsel mit GDB.
Drei Anmerkungen dazu zu den Gruppen 1,
3 und 4, 1 und 4 ist dann ZBH,
die Gruppe 1 ist gleich hier 12.15 Uhr,
also gleich im Anschluss hier dran,
diesen ZBH im Raum
ZPH ist dieses Zentrum für Bio-Informatik, also einfach die Straße runter.
Und dieses willenartige Gebäude, Gruppe 4 ist auch im ZBH,
die ist im Anschluss. Ja, dann Gruppe 3,
die ist auch eigentlich um 12.2.15 Uhr, aber am E-Cum.
Und der Übungsgruppenleiter, der die leitet,
der hat vorher was in der Physik,
deswegen kann der erst um 12.40 Uhr da sein.
Die fängt dann immer erst irgendwie um 12.40 Uhr an.
Könnt ihr heute nochmal mit ihm kurz dann irgendwie diskutieren,
wenn da jetzt irgendwie einzelne Leute früher los müssen oder so,
dann kriegen wir das da wahrscheinlich geregelt.
Aber so die fängt halt immer erst um 12.40 Uhr an.
Und die Gruppe 4,
die da oben schon genannt wurde,
die fängt halt immer um 14 Uhr an
Punkt 14 Uhr. Und auch da könnt ihr nochmal mit Theresa reden,
wenn das da irgendwie ein Problem gibt. Ja,
dann der Ablauf, es gibt alle zwei Wochen neun Aufgabenzettel,
den stelle ich üblicherweise so Montag bis Mittwoch irgendwie ins Netz.
Also zum Beispiel würde ich heute,
wenn ich gleich zu Hause bin und dann nochmal eine Stunde dran arbeite,
dann stelle ich heute den neuen Aufgabenzettel ins Netz.
Dann habt ihr anderthalb Wochen Zeit, um den zu bearbeiten,
nämlich bis Montag in elf Tagen oder was das ist.
Da könnt ihr den dann abgeben, entweder per E-Mail,
eure Übungsgruppenleiter oder eben in Haus C, im ersten Stock.
Da ist so eine Kiste, da stehen dann die
einzelnen Zeitslots drauf, da könnt ihr das reintun.
Auf eure Übungszettel solltet ihr dann immer auch den Namen von
einem Übungsgruppenleiter raufschreiben, sonst können wir das
nicht zuordnen
Genau, und dann werden in der Woche die Übung in der Übungsgruppe besprochen.
Und das war es eigentlich. Und ihr sollt das halt
alle, alle Gruppenmitglieder sollen ihren Lösungsvorschlag irgendwie präsentieren können.
Und insgesamt sollt ihr 50 Prozent der Punkte machen.
Ja, Fragen dazu zum Organisatorischen. Der komische Aufgabe
der Aufgabe. Sprich mal mit deinen Übungsgruppen leider eigentlich,
A. Fragen war gerade, ob wir elektronisch abgeben können,
so je nach Übungsgruppenleiter, wenn er das okay findet,
dann kann man es machen.
Sonst noch?
Fragen wollen
Ja. Stofflich ist das halt in den ersten anderthalb Stunden drin.
Ansonsten, ja, du verpasst ein Drittel der Vorlesung.
Ja. Genau, das, genau,
jemand aus der zweiten Reihe sagt gerade, das ist doof.
Dem schließe ich mich an, das ist irgendwie doof.
Aber vielleicht irgendwie mit der Mitschrift vom Kollegen oder
so dann arbeiten
Also das wäre ja eine blöde Aussage von mir,
wenn ich sagen würde, nee, da verpasst du nichts.
Dann sagen alle, cool, 11 Uhr ist Feierabend.
Es sei denn, wir einigen uns darauf,
dass ihr von 9 bis 12 Uhr nichts verpasst,
den kann ich auch zu Hause bleiben und weiter schlafen.
Da wäre ich dabei. Da war oben gerade noch irgendwie
eine Frage, du? Ja. Jetzt nähern wir uns
dem Limit, jetzt ist es irgendwie auf
Da wartest du wahrscheinlich jetzt Zeit drauf.
Sollen uns einfach melden und dann versuche ich lauter zu reden.
Sonst noch. Organisatorisch. Was ist denn? Was meint dann
? Gut, dann heute in den Übungsgruppen gibt es noch
so einen Zettel mit Präsenzaufgaben. Da wird auch das,
was wir heute machen, dann nochmal so ein bisschen trainiert,
weil das üblicherweise ein bisschen Probleme bereitet immer.
Und dann die späteren Wochen ist es immer so,
dass es halt nach einem ganz klassischen Prinzip einfach immer,
ihr präsentiert dann immer das, was ihr als Lösungsvorschlag eingereicht habt.
Und darüber wird dann irgendwie gesprochen. Also nicht so wie bei FG1,
wo wir irgendwie die Präsenzaufgaben hatten, sondern ganz klassisches Prinzip,
man gibt was ab und darüber wird dann in den Übungsgruppen geredet.
Genau, das gibt es sieben Stück, ne?
Also Übungsgruppentermine sind eher gering. So, wollen wir?
Dann kannst du ja losgehen. Erste Folie,
also erste richtige Folie so
Datentypen, die Vorlesung heißt irgendwie Algorithmen und Datenstrukturen.
Datenstrukturen machen eigentlich keinen Sinn, wenn man keine Datentypen hat.
Ein Datentyp definiert quasi eine Menge von Werten,
beispielsweise die natürlichen Zahlen und Operationen darauf, beispielsweise die Addition.
Aus der Programmierung irgendwie sowas, der Datentyp Integer,
hat auch einen gewissen Zahlenbereich,
halt in dem Fall nur einen endlichen Zahlenbereich und Operationen da drauf.
Eine Addition, Subtraktion, Multiplikation und so weiter.
Das ist ein Datentyp, das sind so die elementaren Geschichten
in den Programmiersprachen. Und jetzt ist halt die Idee,
dass wenn ich jetzt mehrere Datentümer habe, Mehrere Dinge eines Datentyps,
dass ich die dann eben in so einer Datenstruktur zusammenfassen kann und eine Datenstruktur,
das sind dann einfach diese Daten zusätzlich noch mit einer bestimmten Anordnung.
Beispielsweise Arrays, Listen, Stack, Graph, habt ihr,
glaube ich, alle schon mal gesehen so.
Und dann wird halt in bestimmter Weise der Zugriff darauf ermöglicht. Beim Array irgendwie beliebiger Zugriff,
wenn man den Index kennt, beim Stack irgendwie,
ich komme nur an den Kopf des Decks ran und das obereste Element des Decks bei der Liste,
je nachdem, wie die implementiert ist,
meistens nur an den Kopf der Liste und vielleicht noch ans Ende.
Graph, eine ganz andere Datenstruktur,
weil ich jedes Element mit jedem anderen
irgendwie verbinden kann
Beim Arry ist es ja üblicherweise so, dass ein Element
nur mit seinem Vorgänger und seinem Nachfolger irgendwie verbunden ist.
Und nicht mit den anderen sozusagen. Und beim Grafen kann
ich eben völlig beliebig Elemente miteinander verbinden. Deswegen sind die
auch so mächtig und treten in ziemlich vielen Bereichen auf.
Das sind einfach so zwei Definitionen, die man kennen sollte.
Und da jetzt die erste blaue Box für,
wenn euch das jetzt sehr interessiert, wie man sich neue
Datenstrukturen ausdenkt und wie man die quasi ganz formal fassen kann.
Da gibt es so diesen Bereich der ADTs,
diese abstrakten Datentypen oder Gebranche, Datentypen, Datenstrukturen.
Da wird dann mit Allgeberinnen und mit Signaturen gearbeitet
Das ist, das ist jetzt nicht unendlich schwer,
aber das hat es halt schon eine sehr mathematische Notation.
Und in sehr vielen Algorithmenbüchern sieht man das heutzutage gar nicht mehr.
Deswegen das nur so für Interessierte. Wer sich dafür interessiert,
da gibt es so Bücher von Erik in Deutschland,
insbesondere von, dann kann man da mal reingucken.
Ansonsten reicht uns diese ersten beiden Definitionen und dann werden wir
halt im Laufe der Vorlesung so die unterschiedlichen Datenstrukturen einführen,
je nachdem, wo wir sie brauchen.
Also wir werden Datenstrukturen nicht einfach so einführen und nichts damit machen,
sondern wir werden die quasi irgendwie zweckgebunden einführen.
Wenn wir jetzt irgendwie eine Menge von Zahlen sortieren wollen,
dann gibt es Datenstrukturen, die einem erlauben,
das effizienter zu machen als Datenstrukturen, die einem erlauben,
das nicht so effizient zu machen.
Und da werden wir
die dann einführen
Gut, das nur so als Definition am Anfang.
Jetzt das, worum es bei Algorithmen und Datenstrukturen prinzipiell geht.
Wir haben irgendein Problem, wir wollen das lösen.
So, unser erstes Problem, ganz einfach.
Wir haben eine lange Liste mit Namen und wir wollen herausfinden,
ob eine bestimmte Person auf dieser Liste steht, ja oder nein.
Erste Frage, wie machen wir das? Da kann man sich überlegen,
ja, ich gucke mir die Liste an und wenn da draufsteht,
sage ich ja.
Ist ein Lösungsvorschlag, kann man sich darüber unterhalten,
ob das jetzt ein algorithmischer Lösungsvorschlag ist.
Da schließt sich dann die Frage an, was ist eigentlich nochmal ein Algorithmus?
Ich weiß nicht genau, ob ihr das schon in SE1,
SE 2 vielleicht mal so habt anklingen lassen
Es gibt eine mehr oder weniger einheitliche Definition vom Algorithmus,
dass man eben sagt, das soll ein endliches Verfahren sein.
Also es soll nicht so sein,
dass die Beschreibung des Verfahrens schon unendlich ist.
Der Ablauf des Algorithmus ist davon unter Umständen unendlich lange sein.
Da kann man sich noch mal drüber unterhalten. Aber die Beschreibung
des Verfahrens sollte endlich sein. Macht ja auch irgendwie Sinn,
sonst lese ich da immer weiter, was ich tun soll.
Dann kommen die zum Ende so. Dann präzise beschrieben,
da kann man sich jetzt wieder darüber unterhalten,
was soll denn präzise beschrieben sein. Aber möglichst präzise eben,
dass da nicht so Operationen in der Beschreibung drin sind,
wo man
gar nicht weiß,
was man tun soll
Und dann der Kern eigentlich, Eingabewerte in Ausgabewerte umrechnen.
Also ich kriege irgendwie eine Eingabe und ich liefere eine Ausgabe.
Ich kriege zwei Zahlen und ich liefere die Summe.
Ich kriege eine Liste von Zahlen und ich liefere die
sortierte Liste zurück. Irgendwie sowas. Im Allgemeinen deterministisch,
sprich nicht dieser Nicht-Determinismus aus FG1, sondern im Allgemeinen deterministisch haben.
Ausgang ist determiniert. Letzteres bedeutet,
dass quasi bei jedem Eingabe oder bei einem speziellen Eingabewert,
wenn ich den da immer wieder rein tue,
kriege ich immer das gleiche Ergebnis.
Ausgangs determiniert
Genau, und einzelne Schritte sollen elementar sein und effektiv ausführbar.
Das bedeutet, ein Einzelner in einem einzelnen Schritt soll sich
nicht schon irgendwie völlig obskure Berechnungen verstecken,
sondern einzelner Schritt soll eben etwas möglichst Einfaches in der Programmiersprache sein.
So ist es wie zwei Zahlen zu addieren oder eine Zuweisung
zu machen oder so ein Ifs-and-Ls-Konstrukt oder so.
Und auch da kann man sich wieder drüber unterhalten,
ab wann ist es denn vielleicht nicht mehr elementar?
Wenn ich mir irgendwie ein Java hinschreibe, if X größer 1,
dann sieht das für mich sehr elementar aus.
Wenn ich mir den gleichen Code in Assembler angucke,
sieht das irgendwie nicht mehr so elementar aus
Aber üblicherweise arbeitet man dann irgendwie im Pseudo-Code und es ist dann relativ klar,
was irgendwie mit Elementar gemeint ist, effektiv ausführbar,
geht die einzelnen Schritte sollen ausführbar sein,
da soll jetzt nicht irgendwie was drinstehen, was gar nicht geht.
Also wenn da jetzt irgendwie drinsteht, dritter Schritt,
ziehe die Wurzel aus zwei, dann sagt der Computer normalerweise, naja,
Wurzel aus zwei ziehen, kann ich irgendwie nur approximieren,
wirst du in einer bestimmten Nachkommensstelle und eben nicht komplett ausrechnen.
Genau, dann noch Termination und Korrektheit,
korrekt hat es jetzt irgendwie so, ja,
das will man haben, man möchte schon wissen,
dass der Algorithmus tatsächlich das tut,
was ich behauptet habe und Termination, das ist so das,
wo man manchmal ein bisschen aufweichen kann,
aber üblicherweise will man auch,
dass der Algorithmus immer terminiert
Genau. So, im Allgemeinen soll ein Algorithmus ein Problem lösen.
Warum steht da im Allgemeinen? Weil für die Algorithmen,
die wir hier betrachten, wird es immer so sein,
dass wir irgendwie ein bestimmtes Problem haben mit bestimmten Eingabewerten,
wir wollen Ausgabewert haben.
Man kann sich noch ganz viele andere Fragestellungen vorstellen,
zum Beispiel das Routing von Paketen in Netzwerken. So,
das sind üblicherweise keine Algorithmen, die irgendwie terminieren,
sondern die unendlich lange laufen und immer weiter dafür sorgen,
dass die Pakete irgendwie da an Kompositen sollen.
Oder irgendwie der Algorithmus, der in einem üblichen Betriebssystem für
irgendwas sorgt. Die laufen unter Umständen auch unendlich lange.
Ja, und eine Instanz ist eine mögliche Eingabe,
Dann noch, wir benutzen übliche Pseudo-Code-Bausteine. Also wenn ihr gleich
den Pseudo-Code seht, da wird euch, glaube ich,
nichts jetzt irgendwie großartig überraschen. Das kennt man alles,
wenn man irgendwie mal mit einer imperativen Programmiersprache oder einer Objektorientierten
gearbeitet hat, dann kennt man die alle.
Aber ich benutze halt Pseudo-Code-Bausteine für Imperative Programmiersprache.
Das ist jetzt nicht funktionale Programmiersprache oder Logik,
Programmiersprache oder so, sondern das ist eine Imperative Programmiersprache.
Gut, dann. Ja, ich wollte ja Max Mustermann suchen.
Jetzt kriege ich irgendwie einen Array, ich habe das hier
mal A genannt, da stehen ganz viele Namen drin.
Also das ist quasi meine Liste von Namen,
die ich kriege
Ja, und jetzt gehe ich das Array durch und gucke,
ob ich Masks, musste man finden.
Und wenn ja, sage ich, das ist cool und
wenn nein sage, ich würde es doofen.
Das ist ungefähr die algorithmische Wiedergabe dieser ursprünglichen Idee.
Ich gucke mir alles an und wenn er dabei ist, ist schön.
Jetzt kann man sich fragen, ob die Lösung gut ist.
Und ob das besser geht. Für die beiden Begriffe gut und besser,
muss man sich aber erstmal überlegen, was interessiert mich eigentlich?
Das, was uns jetzt erstmal interessiert, ist Laufzeit.
Also wie viele Schritte brauche ich hier,
um das Problem zu lösen?
Wie viele Schritte brauche ich denn da
Also wie viele, ich formuliere es nochmal kurz um,
wie viele elementare Schritte benutze ich da so?
Er sagt minimal, einer maximal N und je nachdem,
was man sucht, so im Schnitt N halbe.
Das mit dem im Schnitt, das ignorieren wir nochmal kurz,
aber er sagt so, zwischen 1 bis N.
Wer hat, ja, fühlt gut, wer findet noch
was anderes? Ja, O hatten wir noch nicht.
O hatten wir ja noch nicht, ne?
Also das ist so, hörst du mir zu?
O hatten wir ja
noch nicht
Also Ufern ist stimmt so, da kommen wir nachher hin,
aber so prinzipiell erstmal. Wie viel? Ja, ja,
das könnte man auch nochmal, das wäre dann so ähnlich wie,
als er meinte, so Enhalbe irgendwie.
Ofern entstimmt, Ufern dann wäre das Richtige,
aber muss man sich irgendwie mal Gedanken machen,
warum man diese Unotation jetzt einführt.
Wer hat denn alle schon die Unotation? Oder Landau-Notation,
wer hatte das alle schon? Könnt ihr euch mal ein
bisschen aggressiver melden? Okay. Ich bin ja beruhigt,
dass bei der Aufforderung niemand auf den Tisch geschlagen hat oder so
Ja, oder auch sein Laptop, ja.
Wenn ihr jetzt alle sagt, Endschritte so, ne?
Es ging ja um elementare Anweisungen. Jetzt kann man sich mal überlegen,
nehmen wir mal an, Max Mustermann ist da nicht drin.
Dann ist es ja das Worst-Case-Szenario. Dann muss ich
das Ding ja komplett durchgehen. Dann habe ich irgendwie hier
oben immer eine Erhöhung. Wenn ich die Vorschleife ausschreibe,
dann passiert da sowas wie jedes Mal, wird I um eins erhöht.
Danach habe ich immer einen Vergleich, ob das I vielleicht
schon zu groß ist.
Falls nicht, gehe ich da rein.
Dann gucke ich,
ob AI Max Mustermann ist
Falls nicht, springe ich wieder irgendwo hin.
Und so weiter. Also das Interessante ist nur,
diese einzelnen Sachen, die ich eben genannt habe,
das ändert nicht so großartig nachher,
was an der Laufzeit des Algorithmus ist, weil es eine Konstante ist.
Und das ist auch je nachdem, wie die Programmiersprache
intern so aufgebaut ist, ist das unterschiedlich viel.
Die eine Programmiersprache macht irgendwie bei der, nehmen wir mal,
bei der Adition, macht die vielleicht nur einen Schritt.
Der andere macht intern bei seinem Prozess oder vielleicht fünf Schritte draus,
weil er das irgendwie, was weiß ich, wie aufsplittet.
Das werden aber immer konstant viele sein. Das heißt,
die spannende Kennzahl ist dieses N, dass man irgendwie sagt,
ich habe da Worst Case irgendwie en mal irgendeine konstante Schritte.
Und dafür führen wir nachher
diese Unnotation ein
Das ist doch so. Ja. Das ist so.
Das ist so. Das ist so. Das ist so.
Das ist so. Das ist so. Das ist so
so. Das ist so. Das ist so. Das
ähm, das ist so ein, ähm, m,
m, m, m, m, m, m,
m, m, m, max, musterman gibt,
und ob man sonst, äh, m, m,
männde durchgehen muss.
Meine Problemstellung war für mich ja nur relevant, steht da
da drauf, oder nicht? Wenn da mehrfach draufsteht,
hier da halt mehrfach drauf. Kann man irgendwie einschränken,
das Problem, sodass man irgendwie sagt, oh,
das will ich vorher rauslesen oder so, ne?
Aber so prinzipiell, wenn da mehrfach draufsteht oder erstmal mehrfach
drauf.
Das macht erstmal nichts
Geht das besser? Also wenn wir jetzt an Laufzeit denken,
Speicherplatz will ich jetzt nicht optimieren, ich will jetzt Laufzeit optimieren,
kriege ich das hin, geht das besser?
Ein Hashtable, oh weia, ja,
das können wir, ja, dann geht es schneller,
aber dann rufen wir Library-Funktionen auf,
wo wir gerade noch gar nicht wissen, wie teuer die sind.
Also muss ich erst mal die Hashtable aufbauen und so.
Ich weiß nicht, ob das günstiger wird.
Zum Beispiel, wenn wir das teuer sortieren
Ja, er sagt, wir könnten das sortieren.
Das haben wir so ähnlich wie bei den Hashdingern,
haben wir jetzt irgendwie so eine Vorberechnung. Jetzt nehmen wir mal an,
das hätten wir bei der Hashtagable auch annehmen können,
aber das führt ein bisschen zu weit gerade.
Jetzt nehmen wir mal an, bei dem Sortieren,
dass sich das lohnt, weil wir quasi sagen,
wir wollen nachher so oft in diese Liste gucken,
dass sich der Zeitaufwand vorher quasi bei der Pre-Berechnung zu sortieren, dass sich das lohnt.
Ansonsten, wenn ich jetzt irgendwie eine Liste mit 100 Namen habe und ich brauche 5000 Schritte,
um die zu sortieren, und danach gucke ich nach,
ob der drin ist, das ist irgendwie Zeitverschwendung,
dann kann ich mir einfach dieses Element angucken und sagen,
okay,
jetzt habe ich sie sortiert und jetzt sagt er,
dann kann ich
an irgendeiner Stelle aufhören
Macht ja Sinn. Ich habe die jetzt sortiert und
jetzt meint das so ähnlich wie ein Telefonbuch oder sowas,
ganz antik, ich gehe die Liste durch.
Und wenn ich irgendwann über das M hinaus bin,
dann kann er ja nicht mehr kommen.
Also kann ich dann abbrechen. So, da würde man jetzt sagen,
das ist vom Worst Case her immer noch nicht schneller,
weil der Worst Case ja immer noch wäre,
er ist nicht drin und ich gehe die ganze Liste durch.
Im durchschnittlichen Fall wird es wahrscheinlich schneller sein,
so dass ich eben sage, okay,
dann werde ich Listen habe, wo er drin ist,
bin ich dann meistens irgendwie schneller.
Aber wenn ich jetzt sortiert habe, kann ich es cleverer cleverer machen.
Also ich mache trotzdem diese Vorstufe mit dem Sortieren,
was kann ich jetzt machen
Ja, das hatte er schon gesagt. Also wenn,
du meinst, wenn du hinter dem Suchwort bist,
kann man abbrechen. Das war diese Idee mit,
wenn ich über den M-Buchstaben quasi hinaus bin, höre ich auf.
Ich kann noch was anderes machen, was kann ich machen?
Genau, man kann hier im Lexikon,
wie dann an der Seite markiert ist,
wenn es um Startup geht und so, kann ich mir irgendwie ablegen.
Gibt der Wunsch da bei M fängt,
bei einem Eintrag sich die 115 an.
Und dann fange ich an und weiß, Max Mustermann,
wenn ich eine M habe,
die erst 30,
Ja, das kann ich, also die Idee war gerade,
ich wiederhole das immer, weil ich mir nicht sehe,
wenn das alle verstehen. Die Idee war gerade,
ich mache quasi vorher noch so eine Vorinitierung und sage,
die Namen mit P fangen ab Index 100 an,
die mit Kuh fangen ab Index 250 an und so weiter.
Und dann weiß ich, oh,
das ist ein M, also springe ich da hin.
Da ist das Problem, ähnliche Begründe wie beim Sortieren.
Wenn ich jetzt mehr suchen will, lohnt sich das,
muss ich auch nur einmal über die Liste gehen.
Aber wenn es mich jetzt echt nur um diesen Max Mustermann gerade,
dann geht es noch effizienter,
aber die ist gute Idee,
die ist cool
Ja, wenn wir die Liste als sortierten Baum aufstellen,
dann können wir einen Baum suchen und dann geht das effizient.
Stimmt, will ich gerade noch nicht vertiefen, stimmt,
will ich ja noch nicht vertiefen.
Da steckt aber eine ähnliche Idee drin wie die,
auf die ich gerade hinaus will.
Bei meinem Baum gehst du ja auch immer nach hinten, ne?
Ja. Das ist jemals eine während dir zu stehen.
Genau. Ich kann immer in die Mitte gucken und bin ich
kleiner oder größer sozusagen und dann springe ich in die Hälfte rein.
Wie nennt man das? Das hattet ihr bestimmt schon
, oder
Binäres. Binäres Suchen? Wer hat das schon Binäres Suchen?
Was ist das? Das, was wir gerade gesagt haben. Okay,
wie nähere Suchen ist die Idee, das habt ihr bestimmt
alle schon gemacht, das ist ein total typisches Kinderspiel.
Kind geht zu Papa und sagt, denkt dir mal eine
Zahl zwischen 0 und 100 aus und ich rate die dann.
Und wenn die Kinder noch nicht so clever sind,
sagen sie, 1, 2, 3,
4 und Papa immer so, nein, nein, nein, nein.
Und Papa denkt sich schon, oh mein Gott,
hoffentlich wird mein Sohn bald intelligenter. Ja,
und irgendwann ist das Kind clever und Zac denkt sich so,
okay, ich fange bei 50 an und Papa muss dann sagen,
klein oder größer, wenn Papa nur nein sagt,
hilft das jetzt auch gerade nicht, ne?
Aber wenn Papa sagt irgendwie, nee,
die gesuchte Zahl ist kleiner, dann weiß ich,
okay, sie muss zwischen 0 und 49 sein,
also kann ich in den Bereich springen
Und wenn sie größer springe ich in den anderen Bereich und
dann halbiert sich das immer.
Das ist genauso wie die Idee mit dem Baum quasi,
weil mein Baum hätte ich auch eine Wurzel gehabt,
das ist sozusagen meine 50.
Und dann gucke ich entweder den linken oder den rechten Teilbaum,
dann wandere ich da auch durch.
Kurzer Exkurs. Wie mache ich das mit mehr Prozessorsystemen?
Viehsechskurs gerade, aber wie würde ich das mit mehr Prozessorsystem machen?
Ihr habt jetzt nicht einen Sohn,
ihr seid in der glücklichen Lage,
ihr habt vier Kinder
Für die Männer im Raum, eure Freundin ist durchgekommen und hat gesagt,
ich bin schwanger, ihr sagt so,
das ist cool, sie sagt, ich kriege Drillinge.
Ich sag so, uh. Ja, da kann man
gleich anbauen. Ja, aber man möglichst da halt irgendwie
aufbrechen, dass man gedacht ist. Ja, fast,
beschreibt man genauer. Ich habe drei, vier Prozessoren,
da war eben noch eine Meldung irgendwo, ja?
Ich versuche, den Prozessor, dieselbe Menge der Liste vorzusetzen
Zurück gleichzeitig. Ah, ich bin mir nicht sicher,
dieselbe wäre ja, also jetzt, ich will ja nicht kleine,
kleine nicht leiden, aber dieselbe und die gleiche,
weil dieselbe macht ja keinen Sinn,
dann arbeiten ja alle mit dem, mit dem Dings,
aber was, du meinst die gleiche Größe wahrscheinlich so irgendwie, ne?
Ja, ja, ja, ja, das geht in
die richtige Richtung. Wenn ihr mehrere Kinder habt,
dann nehmen wir mal, ihr habt zwei, ne,
und ihr habt wieder diesen Zahlenraum von 0 bis 100,
dann sagt das eine Kind 33 und das andere Kind sagt 66.
Und dann könnt ihr herausfinden, in welchem Drittel es ist und
dann springen sie da wieder genau in die Mitten rein.
So könnt ihr das machen. Und dann braucht ihr natürlich irgendwie,
müssen die die Prozessoren noch absprechen können, ne,
also irgendwie müssen die Kinder, wenn ich dem einen Kind sage,
es ist größer und ich sage dem anderen Kind,
es ist kleiner, dann müssen sie wissen,
ah,
okay,
dann muss das in diesem Bereich sein
Genau, so könnte man das machen mit Mehrprozessor-Systemen.
Das war nur für einen Exkurs, dass man das Problem tatsächlich
noch effizienter lösen kann, als mit einem binären Suchen.
Wie viele Schritte brauche ich denn beim binären Suchen?
Also diese Idee mit, ich halbiere immer weiter.
Wie Schritte brauche ich da denn? Ah, meine rechte Seite.
Ja. Ja, Blog von Ende. Weil wenn ich immer weiter halbiere,
nehme ich immer meinen, ich habe am Anfang 1024 Elemente,
habe ich beim nächsten Mal 512, 256, 128,
64 und so weiter.
Das wird genau dieser Lugarithmus von den 1024.
Genau. Also es geht noch besser
So sieht das dann aus. Da sage ich dann irgendwie,
ich habe quasi ein erstes und ein letztes Element.
Am Anfang ist es der Bereich von 0 bis 100 und danach
ist vielleicht der Bereich von 0 bis 49 oder so.
Und dann gucke ich immer, dann nehme ich mir immer genau
das Element in der Mitte raus. Also First ist der Anfang,
das ist jetzt zum Beispiel das Element 0,
last minus First ist dann irgendwie 100 minus 0 durch 2,
dann komme ich genau auf die 50.
Dann kann man sich überlegen, dass man nachher damit immer
genau in die Mitte springt. Und dann guckt man,
ist das Element in der Mitte da gerade,
ist das kleiner als P oder ist das größer als P
Also P ist jetzt mein Max. Mustermann sozusagen. Und
falls AM kleiner ist als P, dann muss ich also
in dem Bereich rechts davon suchen und wenn es größer ist,
P muss ich im Bereich links davon suchen. Und so
setze ich mir dann entweder mein First oder mein Last.
Und wenn AM gerade gleich P ist, dann habe ich
meinen Index gefunden und gehe aus der Schleife raus.
Weil hier kalt, was ist die Abbruchbedingung?
Ein Index ist kleiner Null. Wenn Index M ist,
dann würde ich abbrechen und weiß, okay,
ich habe den richtigen Index gefunden.
Und ansonsten kommt man irgendwann an so eine Stelle,
wo First plötzlich größer ist als Last und dann geht das auch nicht mehr.
Dann weiß man, das Element ist nicht in dem Arry drin.
Und das ist besser, wenn man die Laufzeit betrachtet.
Es ist schlechter, wenn es einem um möglichst einfache Lesbarkeit
im Code geht
Also bei dem anderen Code kann man draufgucken und sagen,
ja, ja, das passt.
Bei dem muss man nachdenken. Ja, genau. Welche
Voraussetzungen haben wir, dass Ary muss halt sortiert sein.
Und das ist jetzt der nächste Schritt. Jetzt haben wir
quasi unser Problem auf ein anderes Problem zurückgeführt.
Jetzt haben wir gesagt, okay, jetzt können wir effizienter
den Namen in der Liste finden.
Aber jetzt müssen wir es vorher noch sortieren.
Das ist doch hier Problem
Ja, genau. Hier, genau, sehr schön.
Sehr gut. Der Datentyp muss auch noch vergleichbar sein.
Also ich muss irgendwie so kleiner, gleich, größer, gleich Operationen haben.
Gilt allgemein beim Sortieren, sonst macht Sortieren keinen Sinn.
Aber genau, ich brauche als Voraussetzung brauche ich auch noch,
dass ich irgendwie die Daten miteinander vergleichen kann.
Wenn ich das gar nicht habe, geht das nicht.
Das ist richtig. Ich glaube, mehr brauchen wir nicht,
ne? Ja, okay, also die Operation in Programmiersprachen,
die man noch braucht, okay.
Aber jetzt, das andere ist wichtig gewesen, genau,
dass die irgendwie vergleichbar miteinander sein müssen.
Also wenn ich sonst,
wenn ich eine Liste habe und da sind irgendwie total unterschiedliche Sachen drin,
dann hilft mir das alles nicht,
dann kann ich nicht sortieren
Hier steht's auch. So, jetzt Sortierproblem. Ich kriege
eine Sequenz. Hier nehmen wir jetzt mal an von N-Zahlen
, allgemein von N-Objekten eines bestimmten Datentyps.
Und gesucht ist jetzt so eine Permutation von diesen Eins bis RAN.
Sprich, es sollen genau die gleichen Elemente sein.
Mit der zusätzlichen Eigenschaft, die sind halt sortiert.
Und genau, was eben meinte, dazu brauche ich natürlich
eine Ordnung auf den Elementen, sonst klappt das nicht.
Hat man da üblicherweise. Dass sie jetzt in Zahlen stehen,
könnt ihr abstrahieren, entweder in Zahlen oder in Zeichenketten oder Engrafen,
die ihr dann einfach vielleicht sortierte,
die dann nach der Anzahl der Knuten in dem Grafen.
Da könnte ich auch Grafen sortieren oder so
Oh. Genau, und da noch zwei Begriffe,
die insbesondere für die Sortierverfahren noch ganz wichtig sind.
Wenn ich zwei Elemente habe in der Eingabesequenz, A1 bis 1, die gleich sind.
Also ich habe zum Beispiel als Zahlenwerte irgendwie sechs, fünf,
drei, fünf, sieben, dann tritt die fünf da ja zweimal auf.
Wenn ich jetzt so sortiere,
dass die Reihenfolge dieser beiden Elemente gleich bleibt,
also dass weiterhin die erste, fünf,
die erste fünf bleibt und die zweite fünf,
die zweite fünf,
dann nenne ich das Verfahren stabil
Noch, wenn ich zusätzlich keinen zusätzlichen Speicherplatz bedarf, nenne ich das Inplays.
Aber wichtig mal kurz dieses mit dem stabil.
Das ist deswegen interessant, weil ihr meistens größere Datensätze habt.
Also ihr habt irgendwie Personaldaten, Vorname, Nachname, Matrikelnummer, solche Geschichten.
Und jetzt sortiert ihr aber beispielsweise nur nach den Nachnamen.
Dann möchtet ihr aber unter Umständen, dass die Reihenfolge,
die beiden Dinger vorher hatten, gleich bleibt.
Also dass das nicht irgendwie plötzlich ausgetauscht wird. Bei einigen Verfahren,
bei einigen Sortierungen möchte man das haben, bei anderen nicht.
Oder bei anderen ist es einem egal,
aber bei einigen will man
es haben
Den beispielsweise erst nach einer Sache sortiert und dann nach der
zweiten Sache sortiert, dann möchtet ihr nicht,
dass die zweite Sache die erste plötzlich wieder aufhebt.
Also in den ersten Nachnamen sortiert und dann sagt als zweites sortiere ich,
nach den Materikelnummern, dann möchtet ihr nicht,
dass durch die Sortierung nach den Matrikonummern plötzlich die Nachnamenreihenfolge sich wieder ändert.
Ja, so, das wollen wir lösen.
Warum machen wir das? Also warum ein Sortierproblem könnte man
jetzt sagen, braucht doch nur eine Library-Funktion für Aufrufen.
Aber warum ist Sortieren so ein zentrales Problem so?
In vielen Sachen ist es irgendwie das Wesen der Anwendung,
also das, was ich überhaupt machen will.
Irgendwie Highschool-Liste in Computerspielen oder irgendwie sowas,
da geht es mir jetzt gerade nur ums Sortieren.
Dann ist es recht häufig eine Vorstufe für ganz viele andere Sachen.
Beispielsweise eben für Suchen, wenn ich effizient suchen will,
in dem Setting, was wir eben hatten,
muss ich
vorher sortieren
Dann als Unterroutine ist auch sowas ähnliches wie als Vorstufe in dem Fall,
aber beispielsweise im Painters-Algorithmus, das ist so ein Algorithmus,
der sortiert grafische Objekte nach ihrer Z-Koordinate sozusagen,
also nachher räumlichen Koordinate und malt die dann übereinander.
Dann wird erst das am weitesten wegstehende Objekt gemalt,
dann das, was dich da dran ist, das,
was dann dicht da dran ist und so weiter
und wird quasi von den hinteren Objekten immer richtig verdeckt.
Wenn ihr die irgendwie anders rummalt,
dann ist plötzlich von dem Haus, ja,
ein Teil des Fensters ganz weit hinten und der andere Teil
ganz weit vorne oder so,
das wollt ihr nicht haben.
Deswegen hat man da sortieren nach Z-Koordinaten-Koordinate
als Unterroutine
Dann, was für uns interessant ist,
man kann an den unterschiedlichen Sortierverfahren sich unterschiedliche algorithmische Techniken angucken.
Da hat man immer dieses relativ einfache Setting, dass man sagt,
boah, ich habe endviele Zahlen und will die sortieren.
Das ist in jedem recht eingängig klar. Und kann daran
verschiedene Techniken illustrieren. Und dann kann man losgehen und
die Techniken eben an anderen Problemen anwenden. Dann,
das ist aus theoretischer Sicht interessant, das ist eins der wenigen Probleme,
für die man eine nicht triviale untere Schranke beweisen kann.
Nicht trivial soll bedeuten, bei den meisten Problemen kann man sagen,
ich brauche mehr als einen Schritt, aber das hilft eigentlich so sonderlich.
Und wenn ihr noch so aus FG1, MPV-Ständigkeit und so erinnert,
das waren ja auch alles irgendwie Annahmen, da ist gar nicht klar,
ob das Ob das wirklich deine untere Schranke ist.
Genau, und dann noch irgendwie sortiert wird halt ständig.
Deswegen ist Sortieren tatsächlich ein sehr zentrales Problem,
irgendwie 80 Prozent aller Anwendungen haben irgendwie was mit Sortieren zu tun.
Glaubt man gar nicht. Ja. Brutforce, wem fällt
ein Brutforce-Algorithmus zum Sortieren ein? Und ich betone Brutforce.
Also wenn jetzt hier irgendwie einer kommt mit und jetzt mache
ich mir drei Stunden lang die und die Datenstruktur und danach
tut dieses und jenes,
dann ist falsch.
Ja, ich vergleiche immer zwei benachbarte Elemente. Das Große schiebe ich
nach rechts. Also ich tausche die aus, ne?
Und jetzt muss ich noch ein bisschen aufpassen, wo ich dann weitermache.
Da mache ich irgendwie mit dem Element immer weiter oder so.
Und genau, dann würde so quasi im ersten Durchgang
das Größte irgendwie ganz nach rechts wandern.
Im zweiten irgendwie das Zweitgröße oder so.
Also ich mache quasi immer mit zwei Tauschen,
mache ich danach immer mit dem Größeren weiter.
Bubblesort, ne? Glaube ich. Bubblesort heißt es,
glaube ich, ja. Anderes noch. Fällt euch noch
ein? Ob die Liste sortiert ist,
seit Jahren
Ja, aber dann sortierst du ja nicht.
Das ist sehr Brutforce, ja, das klingt aber so,
wie wenn mein Algorithmus bei einer Eingabe sagen würde,
kann ich nicht.
So habe ich auch mal Code geschrieben, aber das ist lange her.
Du arbeitest doch, ne? Kommst du bei deiner Firma
mit sowas durch, dann würde ich da auch arbeiten.
Das würde ich, ja, ne? Das würde ich
total faszinierend finden. Bitte? Bogo Sword. Ja,
beschreib mal. Ach so, ist noch die Liste,
auf die jedem Mental Rand in Brutal
Was sortiert ist. Oh ja. Okay,
ich spezifiziere nochmal genau, was ich mit Brutforce meine.
Brutforce heißt, dass sie das Problem lösen sollt.
Erster. Und das ist nicht,
ich nenne es mal, naja, wir sagen mal,
dass es nicht so Bogo sein soll hier.
Das funktioniert zwar, hat aber eine total spannende Laufzeit von möglicherweise unendlich.
Eine minimale Laufzeit von eins, ja, ja,
ja, ja, ja. Bedankt vor, ich glaube,
der Evangelium wird nicht und dann reichen die Schleicher herter.
Gemeinde sind Zahlen, dann speisern man die Zahlen einfach auf
den Speicherplatz mit dem Psalm zum Geist und dann hat man
halt seine Limitele nicht in deinem Liebspeicher dann außen hieß.
Ja. Ja, sehr schöne Idee. Funktioniert nur mit
Zahlen, aber sonst sehr, sehr schön, ja,
genau.
Noch eine.
70 Tage da
Ja, ich bin mir gar nicht ganz sicher.
Also wofür brauchst du die neue Liste? Damit ich...
Jede Medaille. Ich bin mir dann eh weiter.
Beschreib noch mal. Ich fange jetzt mal an,
dass ich zu dem gemeinen Diskument... Ist das großartig,
das kleinste Element unterscheiden?
Entweder fange ich es nach hinten oder nachher auch noch.
Und dann wird es ein Tag ist ja keine Liste,
weil das mag ich so lange mit allen, bis du weiter bist.
Ah ja, ich glaube, das ist so ungefähr das,
was auf die nächsten zweien kommt.
Wenn ich es richtig verstanden habe,
wenn ich bestimmt das Maximum und dann,
genau.
Also vielleicht gehe die Liste durch
Erzähle ich von unten, von oben nach unten,
fuhr er in bis eins und ich bestimme immer das Maximum
in meinem Arry, was ich gerade sortieren will.
Das ist ein bisschen was Maximum mit A. Und dann schiebe ich
dieses Maximum eben an die Stelle. Zuerst die Stelle B. ein,
wer B. N, also an das hinterste Element im RBB,
wie ist jetzt mein Ergebnis, Arry,
dann bestimme ich wieder das neue Maximum in dem R.A.R..,
das ist jetzt das zweitgrößte Element, weil ich das Maximum von eben,
das habe ich gerade noch auf Null gesetzt.
Und dann tue ich das an die vorletzte Stelle von
dem RBB und dann bestimme ich das drittgrößte Element in A
und das tue ich dann und so weiter.
Problem,
ich brauche noch diese Maximumsbestimmung hier
Geht auch relativ einfach. Ich gehe das Ary immer durch
und merke mir zuerst, behaupte ich einfach,
dass Ary das Element an der ersten Stelle sei,
das Maximum, dann gucke ich mir alle anderen Elemente an.
Und wenn ich da irgendwie eins finde,
das größer ist als mein aktuelles Maximum, dann sage ich,
oh, das ist jetzt mein größtes Element und das mache ich halt,
bis ich fertig bin in die Mary.
Dann kann ich immer wieder ein Maximum bestimmen.
Laufzeit davon? Das meint ihr so grob? Laufzeit grob
. Ja, Endquadrat, ne? Hier mache ich,
ich gehe quasi endmal in diesen Rumpf rein
Und ruf also enden mal diese Maximumsfunktion auf.
Und da brauche ich ja hier auch so ungefähr in Schritte.
Und dann habe ich N, mal en viele Schritte,
also irgendwie Endquadrat viele Schritte. So grob. Das mit
dem Grob, das werden wir gleich noch ein bisschen ausspielen,
ein bisschen genauer fassen mit dieser U-Notation.
Anderes Verfahren, ich mache das so wie beim Kartenspielen.
In Search and Sword, also sortieren durch Einfügen.
Ich starte mit einer leeren linken Hand,
das ist quasi die leere linke Seite
meines Aris
Dann nehme ich mir eine Karte von der rechten Seite,
das ist jetzt die rechte Seite meines Earys,
und füge die in der linken Hand an der richtigen Stelle ein,
an dem ich folgendes mache.
Ich nehme das Element und jetzt gucke ich immer,
ist es kleiner als dieses am weitesten rechts stehende Element meines linken Earys?
Und falls ja, gehe ich halt weiter,
bis ich die richtige Stelle gefunden habe.
Also die neue Karte von rechts nach links mit den Karten,
die schon auf der linken Hand sind, vergleichen,
sobald ich eine kleinere Karte erreicht habe, füge ich ein.
Und dann sind eben zu jedem Zeitpunkt die Karten auf der
linken Hand sortiert und die Karten auf der rechten halt noch nicht,
die würde ich noch einsortieren.
Genau, die Karten auf der linken Hand sind,
wenn man das jetzt mit Karten tatsächlich macht, die obersten des Stapels.
Und wie gesagt, wenn man das jetzt mit Earys machen will,
dann ist die linke Seite quasi ein linker Teil des Earys
und die rechte Hand ist der rechte Teil des Earys.
Und dann füge ich nach und nach
die rechten Elemente an der richtigen Stelle im linken Eary
Sieht dann so aus. Man fängt erst bei J gleich zwei an,
weil man quasi sagt, das erste Element,
in dem Arry, das ist meine sortierte linke Hand,
das ist ja nur eine Karte, die ist sofort sortiert.
Und dann geht man quasi in der Weilschleife durch,
nimmt jetzt dieses Element,
das erste Element des rechten Arris und guckt halt,
wenn das jetzt größer ist als das, und es ist okay,
dann ist an der richtigen Stelle, wenn es kleiner ist,
dann muss es denen ja nach rechts schieben.
Der begegnet uns nachher auch nochmal
Was haben wir bisher gemacht? Lineare Suchen und Binäres Suchen.
Lineare suchen wir ganz einfach. Ich gehe das Area einmal
durch, bis ich mein Element finde. Binäres Suchen,
ich springe in die Mitte, gucke,
ob mein gesuchtes Element kleiner oder größer ist als das,
was ich gerade suche, falls größer ist,
gehe ich in den rechten Teil, falls kleiner ist,
gehe ich in den linken Teil.
Brauchen wir aber sortierte Sachen für. Dafür haben wir uns
Maximums heute und in Searchins Ford angeguckt. Maximum Sword,
ich nehme immer irgendwie das größte Element und tue es bei
einem neuen Area an die richtige Stelle, ist also kein In-Place-Verfahren.
Kann man aber eins draus machen. Und in Searchins Sword
modelliert quasi das Kartensortieren nach und ist in Place
Jetzt kann man sich fragen, ist ein Verfahren besser als
ein anderes und was wollen wir überhaupt messen?
Darum soll es jetzt gehen. Das war quasi jetzt
so die Einführung, worum es hier so gehen soll.
Und das machen wir jetzt. Jetzt kommen gleich,
man kann da oben gleich springen, wie von dieser Einführung Motivation,
in die Algorithmenanalyse und dann kommt die fiese Ohnotation.
Das, worum es uns gehen soll, Zeit- und Platzkomplexität betrachten von Algorithmen.
Also erster Schritt natürlich überhaupt ein Algorithmus zu entwickeln. Zweiter Schritt,
ihn als korrekt nachzuweisen und dann interessiere ich mich,
dafür ist er jetzt auch wirklich schnell, benötigt er wirklich nicht so viel Platz,
wie ich vielleicht befürchte, so, was zähle ich?
Eine elementare Anweisung zählt als eine Zeiteinheit
Sprich, alles, was man so irgendwie, eine Addition,
Zuweisung, all sowas ist irgendwie eine Zeiteinheit.
Ein Methodenaufruf ist auch eine Zeiteinheit, es sei denn,
man interessiert sich dafür, wie lange die Methode jetzt braucht.
Dann springt man da eben auch rein. Dann musst du
gucken. Genau, eine elementare Variable als eine Platzeinheit.
Und dann wollen wir das abhängig von der Länge Ende Eingabe zählen.
Das kennt ihr schon von Turing-Maschinen irgendwie, kriegen Wort vorgelegt.
Das Wort hat die Länge N. Wie lange brauche ich,
um das Problem zu lösen? Was hier ein bisschen unterschiedlich ist,
normalerweise nimmt man nicht explizit die Länge der Eingabe,
sondern irgendwie eine Kenngröße.
Wenn ich beispielsweise sage, ich gebe euch einen Array von N-N-Zahlen
, dann ist eine sinnvolle Kenngröße dieses
Eigentliche Länge der Eingabe ist ja meistens größer,
weil jede Zahl noch irgendwie eine bestimmte Länge hat.
Anderes Beispiel, wenn ein Graf gegeben ist,
nimmt man meistens als Kennzahl irgendwie die Anzahl der Knoten.
Vielleicht auch noch die Anzahl der Kanten.
Aber man nimmt nicht so direkt die Länge der Eingabe.
Aber was man halt machen, worauf man achten sollte,
ist, dass die Kenngröße immer in einem sinnvollen Zusammenhang zu irgendwie der tatsächlichen Länge der Eingabe steht.
Sonst macht die Aussage nachher keinen Sinn, dass man sagt, oh,
der Algorithmus braucht Endquadrat, viele Schritte oder irgendwie sowas.
Genau, und wir arbeiten mit Funktionen von den natürlichen Zahlen zu
den natürlichen Zahlen bzw. von den natürlichen Zahlen zu den reellen Zahlen.
Die Idee ist, Argument der Funktion ist eben die Länge
der Eingabe oder diese Anzahl der Kenngröße.
Und das Ergebnis sollen dann die Anzahl der Schritte sein,
die der Algorithmus braucht. Da haben Sie sich schon überlegen,
ein Algorithmus braucht höchstwahrscheinlich nicht 3,4 Schritte,
sondern irgendwie entweder braucht er drei Schritte oder vier Schritte oder so.
Aber es ist bei Angabe der Funktion meistens einfacher,
auch mit sowas arbeiten zu können,
wie Lugarithmus von einer Zahl oder irgendwie Endquadrathalbe oder irgendwie sowas,
was halt nicht immer unbedingt eine natürliche Zahl ist.
Deswegen arbeitet man oft hier mit solchen Funktionen einfach,
dass man sagt, die dürfen auch nach R gehen.
Man rundet dann aber eben immer irgendwie auf oder ab
Deswegen streng genommen könnte man hier auch irgendwie N nehmen und
dann müsste man aber bei jeder Funktion noch sagen,
jetzt nehme ich noch die Betragsstriche und runde noch auf oder
so und damit man sich da spart, macht man das.
Genau, da ist nochmal dieses Beispiel mit dem linearen Suchen von
Max Mustermann und jetzt würde man sich eben dafür interessieren,
jetzt sage ich die Kennengröße, das ist die Länge des Arrays,
das ist mein N und jetzt frage ich mich,
okay, was kommt da eben als Schritte raus?
Und normalerweise müsste man jetzt irgendwie zählen irgendwie,
dass man sagt, okay,
das sind jetzt irgendwie sechsmal N viele Schritte,
siebenmal N viele Schritte oder so und weil einem das aber
nicht so sehr interessiert,
weil das sehr von der Architektur und von der Programmiersprache abhängt
Macht man das eher so, dass man sagt,
deswegen will ich mir jetzt diese O-Notation einführen,
um diese Konstanten verschlucken zu können und einfach schnell sagen zu können,
die Laufzeit dieses Algorithmus ist in O von N.
Dass jeder weiß, ah ja, die ist also so ungefähr linear. Oder ich sage,
die ist in O von Endquadratin, weiß jeder Eier,
die ist ungefähr, fällt sich so wie Endquadrat,
wenn ich Eingabe der Länge 10 habe, brauche ich 100 Schritte,
wenn ich Eingabe der Länge 100 habe, brauche ich 10.000 Schritte.
Immer noch mal mit irgendeinem konstanten Faktor, aber der fällt halt nicht so ins Gewicht
. Wenn ihr euch überlegt, ihr habt einen konstanten Faktor 5,
also 5 mal Endquadrat oder 4 mal Endquadrat,
das unterscheidet sich für große N nicht so großartig.
Deswegen versucht man die zu ja, ignorieren zu können oder nicht aufschreiben zu müssen.
Und genau die sollen jetzt in dieser O-Notation verschwinden, auch genannt Landonnotation. Und die Ideen ist eben Konzentration auf das Wesentliche,
abstrahieren von verschiedenen Rechenarchitekturen und eben,
dass damit ein guter Vergleich von Algorithmen möglich ist,
weil es im Allgemeinen in der Praxis eben doch so ist,
wenn ich sage, ich habe hier einen Algorithmus,
der läuft in O von Endquadrat und ich habe hier einen Algorithmus,
der läuft in O von N hoch 3,
dann ist der quadratische typischerweise wirklich besser.
Bis auf vielleicht mal kleine Ausreißer oder so. Aber üblicherweise ist der
dann besser. Was wir auch noch machen können und wollen,
was wir gleich sehen werden, wir wollen so anfängliche Schwankungen ignorieren,
weil man oft so Sachen hat wie irgendwie Alles bis zur
Größe 4 wird irgendwie durch spezielle Behandlungen im Code abgefangen und erst danach wird es spannend oder so.
Solche anfänglichen Schwanken will man dann ignorieren können. Aber,
was halt passiert, sowas wie 5 mal N und 5000
mal N wird als im Prinzip gleich angesehen,
weil das beides, bei beiden werden wir dann sagen,
oh der Algorithmus läuft in O von N.
Das heißt, wir werden zu so einer Notation kommen,
die sich in der Praxis sehr deutlich bewährt hat,
die auch Sinn macht, die auch bei ganz vielen Fällen jetzt,
was sowas hier 5000,
das wird meistens nicht verschluckt oder so,
das ist irgendwie,
das tritt in der Praxis
eigentlich nicht auf
Aber, ne,
je nach Anwendungsfall sollte man trotzdem unter Umständen nochmal darüber nachdenken,
dass da gerade was verschluckt wird und ob das jetzt gerade von Relevanz ist oder nicht.
Wenn nämlich tatsächlich Algorithmen habt mit solchen Laufzeiten und ihr
wisst jetzt aber, eure Eingabegröße wird maximal 100 groß.
Also euer N wird maximal große 100, dann ist halt,
warte mal, das schlechte Beispiel gerade, der Forderer ist ja immer besser.
Achso, ich wollte das illustrieren mit Exponenten,
wenn ihr irgendwie sowas habt wie 5000 mal N
im Vergleich zu 5 mal Endquadrat oder so,
dann kann halt der Endquadratalgorithmus bei kleinen Eingabegrüßen trotzdem
besser sein
Fünfmal Endquadrat für N gleich 10,
ist irgendwie besser als 5000 mal N für N gleich 10.
Das heißt, manchmal muss man auf die Konstanten noch gucken.
So, ich bin überhaupt nicht mehr mein Zeitplan.
Seid ihr bereit? Ich glaube, die nächste Folie ist die
fiese O-Notation. Ich habe die einfach gnadenlos aufgeschrieben jetzt,
ohne dass das irgendwie so schrittweise aufgebaut wird oder so.
Die steht da jetzt einfach ganz brutal komplett.
Also da kommt noch die Warnung vorne. Es geht jetzt
nämlich die nächsten 20 Folien. Erstmal komplett so um diese
O-Notation und teilweise vergisst man, wo das hinführen sollte.
Deswegen nimmt die 20 Folien jetzt erst mal so mit und
später wird das dann in den Anwendungen sehr deutlich werden,
warum man das bei der Algorithmenanalyse sinnvoll einsetzen kann
Na, Daisy. Boom. Können wir jetzt Pause haben
? Also, die erste da. Die erste ist eigentlich
auch die wichtigste, wenn man die erste verstanden hat,
ergeben sich die anderen so.
Aber die erste sagt, oh, von geh von N.
Ich nehme mir eine Funktion, gehe von N,
zum Beispiel Endquadrat. Dann sage ich in, oh,
von Endquadrat soll das folgende
drin sein.
All die Funktion
Mit der folgenden Eigenschaft. Es gibt irgendeine konstante C,
irgendeine konstant, positive konstante C. Mit der Eigenschaft,
wir ignorieren mal kurz alles andere, das F von N,
kleiner gleich zehnmal G von N ist. Bedeutet,
ich kann das G von N durch die Konstante vielleicht noch so ein bisschen schieben,
wenn ihr euch so einen Grafen vorstellt,
kann ich das noch ein bisschen schieben.
Und das F ist dann da drunter. Oder kleiner gleich.
Betragsstriche können wir für unser Setting eigentlich auch ignorieren, weil wie gesagt,
bei der Algorithmenanalyse kommen negative Zahlen ja eigentlich gar nicht vor,
also in der negativen Laufzeit macht keinen Sinn.
Kleiner gleich Endquadrat, auch wenn das für einige anfängliche Ns
gar nicht stimmt
Ja. Warum will man das haben? Weil wenn ich
einen Algorithmus habe mit der Laufzeit, zehnmal N,
dann ist der zwar am Anfang vielleicht langsamer,
als jetzt einer mit Endquadrat vielen Schritten.
Für Werte 1, 2 und 3 ist er irgendwie langsamer.
Vier auch noch, fünf auch noch.
Und dann irgendwann holt das Endquadrat ihn aber drastisch ein.
Ab dem W10 halt. Genau, ich mache gerade welches
nachher abziehen. Und das will ich damit halt ausdrücken können.
Und dieses mit dem C, das dient halt dazu,
dass man so Sachen machen kann,
wie das dreimal Endquadrat und viermal Endquadrat eben auch in der gleichen Klasse sind,
weil ich dann eben das dreimal Endquadrat unter Umständen
einfach höher schiebe und dann nicht das viermal in Quadrat darunter
Die will ich alle in der gleichen Klasse haben. Ja,
sprich, in O von G von Ende sind alle die Funktionen drin,
die, man spricht von asymptotisch, kleiner, gleich sind,
asymptotisch, das fängt er später an und ich darf auch das G noch nach oben schieben, so.
In Omega von G von Ende sind dann all die Funktionen drin.
Hier kann man schon sehen, da steht überall das Gleiche.
Es existiert ein C aus R plus, es existiert in
der Null und der hat das für alle Enden.
Und dann steht hier eben F von N soll größer,
gleiche C-MAG von innen sein. Da spricht also die Funktionserin,
die größer gleich geh von innen sind. In dem kleinen O hier,
da ist der Unterschied hier vorne, da steht jetzt ein anderer Quanto,
sondern für alle Das führt dazu, dass es asymptotisch echt kleiner ist.
Und das sehen wir gleich am Beispiel. Erstmal könnt ihr
das mal so hinnehmen. Das führt dazu,
dass alle Funktionen, die da drin sind,
echt kleiner sind als G von innen, asymptotisch betrachtet.
Und in dem kleinen Omega wieder genau andersrum,
da wird es halt für alle gemacht und hier stehen größer gleich.
Das heißt, da sind die drin, die echt größer sind.
Und der Letzte, das Täter hier, Täter von G von N,
das ist quasi eine Zusammenfassung von Groß-O und Groß-Omega.
Da sagt man nämlich,
da sind all die Funktionen drin für die zwei solche Konstanten existieren,
sodass dann einmal C-1 mal G, kleiner gleich F von N ist.
Das ist genau das Gleiche wie bei dem Omega,
Klar, ich dem, ne? Und F von ein kleiner,
gleich C2 Magie von Ende, das ist genau das hier.
Bei dem O. Also in Omega sind quasi all die Funktionen drin,
äh, Täter, Entschuldigung,
in dem Täter sind quasi all die Funktionen drin,
die sowohl in O von jederen sind,
als auch in Omega von G. Das führt dazu,
dass die quasi sowohl kleiner gleich sind,
als auch größer gleich, sprich,
sie sind gleich.
Also Täter sind Funktionen drin,
die sich asynthotisch genau gleich verhalten
Gleich sehen wir es am Beispiel. Nur hier schon mal,
dass ihr im Vorgeschmack so die wichtigen Funktionen in der Algorithmenanalyse
konstante Funktionen, Logarithmen, Wurzelfunktionen, Polynome, Exponentialfunktionen.
Das sind eigentlich die, die primär auftreten,
die spannend sind und eben Kombinationen davon.
Irgendwie sowas wie Log-in-Mal-N oder irgendwie sowas oder zwei hoch-N-Mal-N-Quadrat,
solche Geschichten. Das sind die wichtigen und was in
den Hausaufgaben dann passiert in den nächsten Wochen ist,
dass man einmal sich anguckt, den Zusammenhang zwischen den Allen.
Also was ist jetzt in o von der anderen jeweils drin?
Welche ist wirklich kleiner, welche ist wirklich größer und sowas?
Das sollte dann den Hausaufgaben mal machen
Anmerkung noch hier zu diesem Logarithmus-Ding. Wir sind ja in der Informatik,
wir arbeiten jetzt eigentlich nur noch mit dem Logarithmus zur Basis
2. Andere Sachen nur noch in Sonderfällen so.
Und den definieren wir nochmal ganz speziell, dass wir sagen,
der Logorithmus von End soll eins sein,
falls End kleiner gleich eins ist und sonst eben der Norhythmus zur Basis 2 von End plus 1.
Der Sinn davon, es steht da drunter,
dann ist Log von End bei uns immer genau die Länge der Binärdarstellung einer natürlichen Zahl.
Also wenn ich irgendwie sage, 2000,
dann kommt hier bei Log 1000 eben gerade die Anzahl der Witz raus,
die ich brauche,
um die Zahl zu kodieren
Und das braucht man halt bei ganz vielen Sachen bei
den Algorithmen und die Analogerithmen braucht man üblicherweise nicht.
Deswegen arbeiten wir mit dem. Aber das ist auch nicht so super tragisch,
wenn man das vergisst, weil die anderen Algorithmen,
die brauchen alle immer nur so einen konstanten Faktor,
konstanter Faktor wird in der U-Notation Eva schluckt,
also ist O von Login eigentlich das gleiche wie O von Logorithmus zu Basis,
4 von Ende oder zu Basis 7 von Ende und so,
das tut sich nicht viel.
Also in der U-Notation tut sich das nichts.
Die beiden Folien aber nur so als kurzer Einschub,
das gucken wir uns dann nochmal genauer an.
Bei der waren wir eigentlich und jetzt wollen wir mal ein Beispiel rechnen für diese,
ich glaube für die Täter-Notation habe ich mir eins Genau,
für Täter. Oben steht nochmal die Definition zur Wiederholung.
Da steht es auch schon ohne Betragsstrich, also bei der
ursprünglichen Definition hatte ich hier noch irgendwie die Betragsstriche stehen.
Das habe ich mir hier jetzt schon gespart,
weil man das üblicherweise in der Algorithmenanalyse eh nicht braucht.
Und wenn ihr euch hier diese Funktion anseht,
hier ein halb Endquadrat minus 3N. Naja,
für eins wird das irgendwie noch negativ, aber das kann man ignorieren.
Es geht ja sowieso nachher nur um solche Zahlen,
dass sie sagt, irgendwie ab einem bestimmten N-0,
dann ignoriere ich halt den Anfang.
Das ist nicht
so tragisch
Wenn ich das zeigen möchte, dass ein Halb-Endquadrat minus 3N,
im Grunde genommen das Gleiche ist wie Endquadrat,
dann könnt ihr euch überlegen,
wenn ihr da irgendwie den Wert 5 einsetzt,
dann gibt es da noch einen ganz schönen Unterschied.
Wenn ihr irgendwie den Wert 50 einsetzt, wird der Unterschied schon kleiner.
Wenn ihr den Wert 5000 einsetzt, wird der Unterschied halt
immer weniger relevant. Deswegen will man in der Algorithmenanalyse sagen,
dass die beiden Funktionen im Grunde genommen gleich sind.
Was wir also suchen, wenn man sich die Definition anguckt,
wir suchen jetzt solche konstanten C1, C2 und N0,
sodass einmal C1 mal N2,
kleiner leicht dem ist und einmal größer gleich dem mit der
anderen Konstante
Ja, C1 und C2, da darf man irgendwie dran spielen.
Und an dem N darf man eigentlich ausspielen,
weil man das ja erst ab einem bestimmten N0 machen muss.
Jetzt kann man überall durch Endquadrat teilen und dann sieht das so aus.
Jetzt muss man sich eben überlegen, ab welchem Ende gilt das
da und was muss man dann für C1 und C2 wählen?
Ich habe das da so gemacht,
da gibt es ja auch noch beliebig viele andere,
aber ich habe halt N024 gewählt,
dann steht hier irgendwie ein halb minus ein Achtel,
also kommt da irgendwie drei Achtel raus.
Und danach nähert es sich ja immer mehr dem einen Hype an,
also kann ich für das C1 irgendwie zwei Achtel wählen und
für das C2 wähle ich eins,
dann ist gut
Kann ich auch anders machen. Ja. Was würde man machen?
Und das kann man für die U-Notation genauso machen und für
die Omik auch. Dann ist man dieses zweite Planeten.
Genau. Also für die U-Notation macht man es genauso,
lässt dann nur den Teil hier weg, das kleiner gleich da.
Für die Omikanotation macht man es auch so, lässt den Teil hier weg.
Dann kann man das genauso machen. Ist aber umständlich,
also diese Sachen, sich ständig zu überlegen, ist relativ umständlich.
Deswegen arbeitet man relativ häufig mit diesem Satz. Den wollen wir jetzt nicht beweisen,
den wollen wir einfach nur benutzen, dass man halt sagt,
F von Ende ist in U von G von Ende drin,
genau dann,
wenn der Limes von F von N durch G von N
kleiner ist als unendlich
Und die anderen sind so ähnlich definiert. Ja. Großen Buchstaben. Ja,
die Frage war gerade,
wenn etwas in den beiden großen Buchstaben drin ist,
also wenn etwas in den Ofern gehe ist und in Omega von gehe,
also Groß-O und Groß-Omega,
dann ist es auch in Großtäter
Also man könnte jetzt auch sagen,
schon mal ein Vorgriff auf gleich, was noch kommt,
FSNO von G drin, genau dann,
wenn der Lieben ist, eine konstante C ergibt,
die größer ist als Null und kleinerseits unendlich.
Weil dann hast du einmal das, das ist kleiner als unendlich und
einmal das ist es größer als Null und dann weißt du,
es sind Täter von G drin.
Bitte? Ja, aber trotzdem, vertrau mir.
Das ist ja auch nicht die Konstante aus der vorherigen Definition.
Du hast ja gerade selbst gesagt,
wenn etwas in den Ofen gehst und in Omega von geh,
dann sollte es doch ein Täter von dir sein.
Naja, in den Ofen geh ist es,
wenn dieser Lieben es kleiner sei zu endlich,
in Omega,
wenn er größer ist als Null
Also muss bei dieser Liebesbildung irgendwie eine konstante CE rauskommen,
die kleiner ist als in Händchen größer als null.
Genau. So, und jetzt kann man einige,
ach genau, jetzt kommen noch ein paar Sätze,
gleich und sowohl die Sätze lassen sich damit schneller zeigen,
als auch unter Umständen das, was wir eben gemacht haben,
geht damit meistens auch sehr viel schneller.
Das ist das gleiche Beispiel wie eben, wenn man das hier zeigen will,
einhalb Endquality News 3, ein Element aus O von Endquadrat,
also es fasst das gleiche wie eben die gleichen Funktionen,
aber wir zeigen jetzt eine O von N,
Quadrat und nicht Täter von Endquadrat,
dann bildet man halt den Limes von der Funktion geteilt durch Endquadrat,
Dann hat man den Liebes hier.
Das ist auch ziemlich genau das, was wir eben auch hatten über
dieser Bruststrichschreibweise. Naja, wenn Ende dagegen unendlich wandert,
dann wird dieses Drei durch Ende immer kleiner.
Nähert sich, dann nähert sich dieser ganze,
das Ganze da, nähert sich dann neben einem halb ein.
Und ein halb ist kleiner als unendlich. Also wissen wir,
F von Ende ist Element aus Ofen-G von Ende.
Und genauso kann man dann sagen, es ist auch hier größer als null.
Ein halbes offensichtlich größer als null. Also es ist auch
ein Omega drin und dann ist das eine Täter drin.
Ja. Kleine Merkhilfe
Was ist jeweils gemeint? FNU von G, F,
Kleinergleich G, F in Omega von GEF, größergleich G,
F in TT, GEF, gleich G und so weiter.
Und immer asymptotisch gemeint. Also erst ab einem
bestimmten Wert und ich habe noch diese Konstante zum Schieben.
Wem ist aufgefallen, wo die Notation fröhlich durcheinander geht?
Ja, ich habe hier fieses Notationswirr wahrgemacht.
Wem ist das aufgefallen
Ich weiß nicht, habe ich hier Gleichheit irgendwo?
Nö, ich habe hier überall Elementszeichen. Das meine ich
nicht. Aber wenn ihr euch das hier anguckt,
hier schreibe ich immer irgendwie F von N-Element O von G von N.
Und hier schreibe ich jetzt F-Element O von G. Ich meine gut,
das soll das auch nur eine Merkhilfe sein, aber das habe ich deswegen gemacht,
weil das tatsächlich in der Literatur auch durcheinander geht.
Also im Kormen, wenn ihr dieses Buch kommen, wenn ihr da mal reinguckt,
da ist es so, dass da das Täter definiert,
irgendwie TTG von N ist gleich, bla bla bla.
Und eine Seite später definiert der O von F ist gleich bla bla bla.
Eigentlich ist ja F was anderes als F und N und so.
Aber das geht halt in der Notation bei den meisten fröhlich durcheinander.
Ich habe es jetzt hier so gemacht,
dass ich quasi auf den ersten Folien immer mit F von N
gearbeitet habe und jetzt kommt so ein 3-4-Folien-Block,
wo ich einfach nur mit F und G arbeite,
weil es da mehr um Beweise geht und nicht so direkt um die Funktion selbst.
Und damit ihr euch ein bisschen daran gewöhnt,
dass das von der Notation ein bisschen schwammig ist,
nicht so exakt wie andere Sachen in der Mathematik,
aber man im Grunde genommen immer genau weiß, was gemeint ist.
Die anderen Sachen, wo es von der Notation ein bisschen
durcheinander geht, ist das mit den Betragsstrichen.
Das hatte ich euch ja schon gesagt,
dass du in der ursprünglichen Definition die Betragsstriche drin sind.
Man braucht ja mit einer Algorithmenanalyse nicht,
deswegen stehen die da nicht. Und was noch ist,
ist, ich habe es hier immer mit Elementzeichen geschrieben,
das werde ich auch weiterhin so machen,
was hier viel in der in der Literatur findet,
ist, dass deine Gleichheit steht.
Dass da steht, F ist gleich,
O von G. Also N ist gleich O von Endquadrat.
Das kann man auch machen,
dann hat man meistens so lange Gleichheitsketten nachher bei den Umformungen.
Und dann muss man wissen, wenn man bei der O-Notation ist,
darf man diese Gleichheit irgendwie nur von links nach rechts lesen und nicht von rechts nach links.
Das ist also nicht so Gleichheit wie im üblichen Sinne.
Die drei Anmerkungen beim nächsten Foliensatz tue ich die noch mal
in rot auf eine Folie. Lasst euch davon nicht verwirren
. Also das wäre jetzt quasi RVM und der Überlegter.
In dem Setting ja. Also sonst,
weil in dem Setting immer klar ist, was gemeint ist.
Streng genommen wäre sowas wie O von
Der F eine Funktion, dann kann ich eigentlich nicht hinschreiben,
oh, von Endquadrat, würde ich aber ganz häufig machen.
Und ich schreibe O von F und N,
dann meine ich eigentlich ein ganz besonderes Bild.
Deswegen läuft das irgendwie munter durcheinander. Gemein sind tatsächlich immer
das in diesem O von F-Funktionen drin sind,
die in einer bestimmten Eigenschaft mit dieser anderen Funktion F stehen.
Aber für die Notation wäre es eben irgendwie potthässlich,
wenn man nicht einfach schreiben kann, oh, von Endquadrat.
Weil ich das halt gerade ausdrücken will,
dass dieses O einfach nur C verschluckt.
Ja, jetzt kommen drei Folien mit fiesen Sätzen
Jetzt hat man diese O-Notation, als will man damit auch
ein bisschen arbeiten. Und man will so Schlussfolgerungen machen,
zum Beispiel das erste hier, das ist einfach so eine Transitivitätsgeschichte,
dass ich irgendwie sagen kann, wenn F in,
skillt hier tatsächlich für alle diese Xe,
wenn F in O von je ist und gehe es in O von H,
dann impliziert das FS in O von H. Wenn ihr an diese Merkhilfe hier,
FNO von G bedeutet F. Kleiner gleich G,
dann ist das relativ klar.
Wenn F. Kleiner gleich G ist und gehe kleiner gleich Haar,
dann ist auch F. Kleiner gleich Haar.
Wenig überraschend. Oder hier auch F-Element X von F
für genau die drei Dinger. Bei O, Groß,
Omega und Täter, da steht hier ja überall noch
die Möglichkeit mit der Gleichheit
Ja, das ist auch klar,
dann ist F natürlich ein O von F und F,
auch in Omega von F und so, weil die ja gerade gleich sind.
Und hier das Gleiche. Also mit den Merkhilfen sieht man sofort,
dass man den Sätzen glauben kann,
aber die Merkhilfe ist ja nur so eine Merkhilfe,
wo man beweisen die, dass das auch funktioniert.
Wir machen das einmal für erstens und x gleich, oh.
Wenn F in O von G ist und GNU von H,
das ist ja das, was ich hier benutzen darf,
F in O von G und G in O von H,
dann, ja, was weiß ich jetzt?
Es gibt irgendwie so ein C und eine Null,
so das F von ein kleiner gleich C Magie von Ende
ist,
ab irgendeinem bestimmten Index
in Null
Genauso weiß ich, weil G ja auch ein Uhr von H ist.
Das ist noch so ein C-Strich und so ein N-0-Strich gibt,
sodass im Grunde genommen das Gleiche gilt nur jetzt eben irgendwie
für G von N-Strich und H von N-Strich hier und Absomm.
Anderem Index, N-0-Strich. Naja, was mache ich jetzt? Ich weiß,
F von Ende ist kleiner gleich zehnmal G von N und ich weiß,
G von N ist kleiner gleich zehnmal H von N.
Die beiden will ich irgendwie miteinander verbinden. Ja,
und jetzt ist noch das Problem,
vielleicht starten die ja bei unterschiedlichen Indie-CSN-0 und N-0-Strich.
Also nehme ich mir den größten davon,
dann weiß ich, das gilt jetzt bei beiden,
diese Ungleichung
Das gilt nämlich für alle N-Strich-Strich-Größe gleich als N-Dur-Strich.
Beide Ungleichungen. Und für die kann ich dann sagen,
F-V-N-Strich-Strich ist kleiner gleich zehnmal, geh von N-Strich-Strich.
Kleiner gleich zehnmal C-Strich mal. Das, ne?
Also hier müssen noch die zwei Striche hin.
Also die eine Ungleichung da weglassen, da habe ich insgesamt F-V-N-Strich-Strichs
Kleinergleich. Dem da. Und weil zehnmal C-Strich wieder eine Konstante ist.
Irgendeine andere, zehnmal zig Strichhalt. Habe ich gezeigt,
dass F von N-Strich-Strich kleinergleich C-Strich mal Hafen N-Strich-Strich ist,
also das F in Ofen haben.
Und für die anderen geht das genauso.
Da arbeitet man halt irgendwie mit. Größer gleich und eventuell
bei dem Täter mit zwei Ungleichungen und so,
aber das läuft alles aufs Gleiche hinaus
Das gilt auch alles, Gehe-Element aus O von F,
genau dann, wenn F-Element aus Omega von G,
auch da wieder mit der Merkhilfe,
wenn GNO von F ist,
bedeutet das G ist kleiner gleich F. Naja,
dann bedeutet das auch, dass F größer gleich G ist.
Passt irgendwie zusammen. Und bei den anderen genauso mit kleiner und größer,
G in TTF genau dann,
wenn es in O von F und Omega von F ist,
also wenn G sowohl kleiner gleich ist als
auch größer gleich,
dann muss es
gleich sein
Klein-O von F ist eine Teilmenge von Großuf von F,
Klein-Omega von Epheser Timing von Großomega von F.
Und jetzt noch die beiden Dinger da mit dem Fragezeichen.
Was kommt bei sechstens und siebtens raus?
Was ist der Schnitt von Klein-Omega mit Klein-O?
Wenn ihr an die Merkhilfe denkt? Genau, leer,
ne? Omega von Efter sind all die Funktionen drin,
die echt kleiner sind als F. Und in O von F sind all die Funktionen,
Klein-Omega von Nationali die Funktionen drin, die echt größer sind als F.
Und einen kleinen O von F sind all die drin,
die echt kleiner sind.
Und keine Funktion kann gleichzeitig echt kleiner und echt größer sein,
also funktioniert das nicht.
Und das siebte hatten wir schon,
Täter, ne? Genau, das lief das Täterste,
ja quasi, steht das hier als drittes, ne?
Also, beim siebten kommt ja Großtäter von Effin,
das sagt das dritte auch schon hier, und hier kommt halt die leere Menge hin.
Und wenn man jetzt viertens beweisen will,
und das machen wir immer mit dem Limes,
dann nimmt man also eine Funktion hier, geh,
die in O von Eff drin ist,
dann weiß sich der Limes von F.N. durch GN, geht gegen Null.
Das darf ich benutzen. Jetzt überlege ich mir,
was muss ich eigentlich zeigen, wenn ich zeigen will,
dass G-Element von O von F ist,
und dafür muss ich einfach nur zeigen,
dass der Limes irgendwie gegen eine konstante C geht.
Naja, und Null ist eine Konstante, ne?
So ist, dann sage ich einfach mit C
gleich Null folgt das sofort und bin fertig.
Der ist einfach
Auch von der Notation her ist das irgendwie,
also der Beweis an sich ist eigentlich einfach, aber von der Notation her ist es gewöhnungsbedürftig.
Und zu guter Letzt, die noch, wenn ich zwei Funktionen habe,
die ein O von H sind, dann ist auch die Summe ein O von H.
Wenn ich eine Funktion habe,
die ein O von G ist und ich habe noch eine Konstante,
dann ist auch zehnmal F in O von G und wenn ich eine habe,
die ein O von H1 ist und eine habe,
die ein O von H2 ist,
dann ist das Produkt in O von H1 mal H2.
Da wird es jetzt schon so ein bisschen schwieriger mit der Merkhilfe,
weil hier sage ich, F und G sind beide kleiner
gleich Haar von der Idee her und jetzt behaupte ich plötzlich,
ja,
dann ist auch die Summe kleiner gleich Haar
Das ist irgendwie, da würde man jetzt erst mal so von der Idee,
würde man sagen, nö, nö, nö.
Das gilt erst mal nur für das O.
Also bei den anderen müsste ich jetzt nachdenken,
das wird so ein bisschen, ich glaube,
da klappt es auch, aber nicht bei allen.
Wenn wir das erste machen, der Grund,
warum das hier klappt, mache ich das überhaupt?
Achso, ne, ich mache das erste gar nicht.
Das erste sollte ja als Dings machen. Das erste sollte
gleich in den Übungen machen, fällt mir gerade ein.
Kann man sich mal überlegen, dass das klappen muss,
weil ich noch diese,
diese konstante C,
mit der darf ich ja rumspielen
Wenn F kleiner gleich Haar ist und G, kleiner gleich Haar,
dann ist F-Plus G eben kleiner gleich zweimal Haar.
Und diesen Faktor darf da ja einfach reinschmeißen. Das dritte wollte ich
hier machen. Wenn ein FNO von H1 ist und GNO von H2,
dann gibt es wieder so ein C und so ein N-0 mit
diesen Eigenschaften und eben so so ein C-Strich- und N-U-Strich mit der Eigenschaft.
Und jetzt kann man einfach,
genauso wie wir das eben auch gemacht haben,
einfach wieder sagen, okay,
dann nehme ich mir das Größte von diesen N-0 und N-0-Strich,
dann gelten nämlich beide Ungleichungen und dann multipliziere ich einfach die
linke und rechte Seite und dann kommt irgendwie sowas raus hier
F von n-strich-magie von n-strich-strich ist kleinergleich, zehnmal c-strich mal,
die beiden Funktionen da. Für eben die n-strich-strich,
die größer sind als das Maximum, von dem man,
also das hier Maximum von N-0 und N-0-strich,
das wird mein neues N-0-strich-strich, ab dem es losgehen soll.
Und dann ist sie halt wieder zehnmal z-strich eine Konstante und damit habe ich gezeigt,
dass F mal G eben in O von H1 mal
hat zwei sind.
Zur Übung. Ich glaube, eine oder zwei stehen auch auf dem Aufgabenzettel drauf.
Ihr könnt mal probieren, wenn ihr das einüben wollt,
einfach alle, alle mal kurz beweisen oder so.
Oder halt welche rauswählen, müsst ihr sicher seid, so ja,
ich weiß, wie das funktioniert. Und was ihr auch noch machen könnt,
ist, wenn G eine der üblichen Funktionen so ist,
also irgendwie ein Polynom, eine Wurzel, nur Rhythmus, irgendwie sowas,
dann mal für jedes von diesen Dingern hier eine andere Funktion F überlegen,
die eben in X von G drin ist.
Das baut ganz gut Intuition auf. Also wenn GN-Quadrat ist,
dann überlegt ihr euch jetzt mal eine Funktion,
die in O von Endquadrat ist, eine,
die in Omega von Endquadrat ist, eine,
die ein Täter von Endquadrat ist und so weiter.
Dann seid ihr nachher ganz,
ganz Firmen in der Notation
Jo. Frage, ja. Ob Funktion, die NO von Endquadrat sind,
auch immer ein O von Ennen sind. Nee, gerade nicht,
weil ein O von Endquadrat sind ja all die Funktionen,
die kleiner gleich, äh, mit kleinerrecht Endquadrat sind, ne?
Und in O von En ja nur die Funktionen,
die kleiner gleich enden sind. Jetzt ist beispielsweise Endquadrat
kleiner gleich in Quadrat, aber ja nicht kleiner gleich
N. Andersrum klappt es, ne? Die,
die NO von En sind, die sind auch alle
ein O von Endquadrat
So, und zum Abschluss nochmal die Algorithmen hier.
Den hatten wir ja schon. Und da hatten wir ja
eigentlich auch schon das Ergebnis, dass wir gesagt haben,
Laufzeit ist linear in der Länge Ende des Arrays.
Also ist das in O von N oder eben
sogar in Täter von N. Was wir noch zeigen müssen,
ist, dass der Algorithmus tatsächlich korrekt ist.
Das wäre bei dem Algorithmus jetzt relativ einfach.
Aber genau, bei den späteren Algorithmen wird das schwieriger.
Kurzer Exkurs übrigens, aus irgendwelchen Gründen. Ich habe das
noch nicht korrigiert gekriegt. Immer wenn ich solche Folien hier habe,
das ist jetzt eigentlich eine Folie, wo unten noch was verborgen wird.
Und beim nächsten Klick kommt das dann.
Und aus irgendwelchen Gründen springt mir da oben immer
diese Algorithmusnummer
9, 10, 19. Das ist halt die, die automatisch generiert ist.
Deswegen steht da immer extra noch irgendwie was von mir oben drüber.
Ja, damit ihr wisst irgendwie, das ist der Algorithmus,
um den das jetzt halt irgendwie geht.
Das ist jetzt, also das sage ich euch deswegen,
damit ihr nicht irgendwie denkt, so oh,
das eine ist Algorithmus 9, das eine ist Algorithmus 10,
versuche ich mal den Unterschied zu finden, so.
Das mache ich dann schon irgendwie ein bisschen offensichtlicher,
dass da ein Unterschied ist. Es führt halt nur dazu,
dass wenn ihr euch die Folien anguckt,
genau wie sie jetzt in der Vorlesung ablaufen,
dann ist da dieser komische Sprung drin, von 9 auf 10.
Und wenn ihr euch die generierte Handout-Version anguckt,
dann gibt es da
gar keine neuen
Dann gibt es ja ja nur die Folie direkt, das ist dann gleich
die 10. Also lasst euch da nicht davon irritieren, dass dann dann Nummern fehlen so.
Es springt dann halt von Algorithmus 7 direkt zu 10 oder so.
Und wer weiß, wie man das beim Beamer-Package und Algorithmen-Package beheben kann,
kann mir aber Bescheid sagen, ich habe es irgendwie noch nicht gefunden. Ja,
die anderen, Fakultätsfunktion hier, wir fangen an,
Resultat ist eins und dann gehen wir eine Steife durch,
eins bis N und multiplizieren im Rand,
also überrechnen einmal zwei, das Ergebnis moditieren mit drei,
das Ergebnis multiplizieren wir mit vier,
das Ergebnis mit fünf und so weiter,
kommt die Fakultät raus.
Immer noch was? Ja,
immer noch O von N. Üben wir das mal gleich ein,
immer noch O von N. Laufzeit ist O von N,
aber Achtung, warum, Achtung?
Was stört einen vielleicht? Wenn ich lese,
die Laufzeit ist in O von N,
dann denke ich, geiler Algorithmus, lineale Laufzeit.
Ja, geht in die richtige Richtung. Er sagt gerade,
die Zahlen werden schnell sehr groß und man braucht interne Rechenschritte,
geht in die richtige Richtung
Wir haben ja gesagt, irgendwie die Kenngröße,
also wenn wir jetzt sagen, Ende ist die Kenngröße,
wir wollten ja,
dass die Kenngröße ziemlich dicht ist an der eigentlichen Größe der Eingabe.
Ist das hier so? Nee, das ist eine Vollkatastrophe
. Die eigentliche Eingabegröße des Logarithmus von N. Das heißt,
ich habe einen exponentiellen Unterschied in meiner Kenngröße und der eigentlichen Eingabe.
Und das ist doof. Also es stimmt zwar zu sagen,
dieser Algorithmus läuft linear in N,
aber in der eigentlichen Eingabegröße hat er eine exponentielle Laufzeit
Wenn ich euch als Zahl, ich schmeiße da 1024 rein,
dann ist die Eingabegröße irgendwie zehn,
weil ich nur zehn Bits brauche, um 1024 zu codieren.
Die Laufzeit ist aber 1024 Schritte. Deswegen ist das dann irreführend, klar.
Du guckst noch so zweifelnd. Klar. Also da nochmal,
damit ihr das, das ist so das Standardbeispiel,
mit dem man einmal illustrieren kann. Achtet darauf,
dass es O von N eben nicht unbedingt Lineallaufzeit bedeutet,
sondern dass ihr irgendwie darauf achten müsst,
wie die Kenngröße mit der eigentlichen Eingabe zusammenhängt
Ja, zusammenfasst hier vorgehen, wenn wir so einen Algorithmus analysieren wollen.
Wir überlegen uns bezüglich welcher Kenngrößen wir messen wollen.
Kann sich von der Größe der Eingabe unterscheiden,
sollte aber eben nach Möglichkeit das Ergebnis,
was ich eigentlich transportieren will, nicht verwässern.
Weil wenn ich so wie eben sage, ey,
der Laufzeit, der Algorithmus hat lineare Laufzeit,
dann ist meine erste Intuition eben linear, ist super.
Und das ist in dem Fall gar nicht so.
Bei dem Beispiel kann man jetzt noch sagen, naja,
okay, so wie groß soll die Zahlen schon sagen,
die man da reinsteckt oder so.
Aber bei späteren Algorithmen will man eben nicht
sich so verwirren lassen
Genau, und dann wollen wir Laufzeit und Speicherbedarf bezüglich dieser Kenngrößen ausdrücken.
Ups. Und dann eben noch mal überlegen, ob das jetzt
die Aussage verfälscht oder eben nicht so wie bei dieser Fakultätsfunktion.
Und unten sind noch mal zwei Beispiele,
wo das mit den Kenngrößen okay ist und wo nicht.
Wenn ich einen Grafen mit Endknoten habe und ich drücke dann die Laufzeit bezüglich dieses Ends aus,
dann sagt man üblicherweise, okay, jedem ist klar,
was damit gemeint ist, auch wenn man weiß, dass die Eingabegröße,
wenn das jetzt als Addiazenzmatrix gegeben ist, ein O von Endquadrat ist.
Das ist jetzt nicht so tragisch. Aber wenn man sowas hat wie eben,
wo man so einen exponentiellen Sprung drin hat,
dann ist das schon irreführend
Jo. Finde Maximum. Laufzeit hatten wir schon, ne?
Wiederhof von N. Wieder linear in der Länge des Arrays.
Ich gehe hier. Komme eng mal in diesen Rumpf
rein und sage, die Laufzeit ist in O von N.
Das O verschluckt diese Konstante, dass ich sage,
da versteckt sich eigentlich noch so viel drin.
Und dann sage ich, die Laufzeit ist in O von N.
Und was wir immer machen, das muss ich auch nochmal betonen,
auf irgendeiner Folie, die Laufzeitanalysen, die wir hier machen,
das sind immer Worst-Case-Analysen.
Also wir hatten ja vorhin kurz bei dieser Diskussion,
dass jemand gesagt hat, so naja,
aber im Mittel ist es ja nur eine halbe oder so.
Stimmt alles, aber wir machen erstmal nur Worst-Case-Analysen.
Also was ist die Laufzeit im schlimmsten Fall?
Und hier ist der schlimmste Fall eben,
dass das Eric komplett durchwandern muss und dann habe ich eben
O von N
viele Schritte
Dass es ganz viele Fälle gibt, wo das auch besser ist,
ist okay, aber erstmal interessiert mich nur die Worst-Case-Laufzeit.
Sortieren mit Max. Hatten wir auch schon. Oh,
von Endquadrat. Warum? Weil ich halt N mal in
diesen Schleifen umfreien gehe, aber ich in der Zeile 2
hier auch endviele Schritte brauche.
Oh, Insertionsword.
Wie lange brauche ich da denn
Dann fangen wir damit vielleicht gleich nach der Pause an.
Das ist doch gut. Das Ergebnis steht in den Folien
, aber...
Das ist voll lustig
Ich habe mal zwei, drei Beispiele übersprungen. Wenn ihr
das zu Hause nacharbeitet, da steht auch das Ergebnis.
Wir besprechen das gleich nochmal im Plenum. Die drei Beispiele.
Das noch für die U-Notation, dass die halt so konstanten verschluckt.
Oh, von Ende kann man auch sagen, das verschluckt
quasi so eine Konstante irgendwie wie acht oder neun oder tausend oder so.
Und dann ist das okay. Und jetzt ist aber das Problem,
wenn die zu groß oder klein sind, kann das das Ergebnis verfälschen.
Da steht nochmal das, was ich vorhin einmal versucht habe,
verbal zu erzählen, wenn ich jetzt so Extreme habe,
wie irgendwie zehn hoch, sechsmal N und zehn hoch,
minus zehn mal zwei hoch N, dann ist eigentlich dieses Ding,
wo ich sagen würde, exponentielle Laufzeit, lange,
lange,
lange Zeit besser als das hier
Also das dauert schon, da muss ich schon mit
ziemlich großen Eingaben kommen, bis die Exponentialfunktion sich durch,
bis die durchschlägt und tatsächlich dieser rechte Bereiche größer wird.
Von der U-Notation würde ich immer nur noch sagen,
das hier ist schlechter als das.
Also die ja besser, Entschuldigung, linear ist besser als exponentiell.
Aber in der Praxis kommt sowas meistens nicht vor.
Dass man sowohl extreme Sachen hat. In der Praxis ist es meistens so,
dass wenn ich weiß, ein Algorithmus hat lineare Laufzeit,
dann ist es auch tatsächlich besser, als einer mit exponentieller Laufzeit.
Aber wenn man gerade an irgendwas sehr Speziellem sitzt so,
dann muss man sich halt unter Umständen tatsächlich nochmal angucken,
welche Konstanten werden da verschluckt und wie arbeite ich damit
Genau. Zu Merkregeln, was hatten wir für Laufzeiten,
konstante Laufzeit, das ist ganz selten,
aber Grundoperationen kosten konstant viel. Lugarithmisch bei wiederholtem Halbieren,
so wie wir das beim Vinären suchen hatten,
oder wenn man irgendwie einen Baum hat und da mit der Höhe irgendwie arbeitet,
also ich fange mal mit der Wurzel an und wandere irgendwie ein Zweig bis zum Blatt herab,
dann habe ich auch irgendwie was Logerithmisches.
Lineare Laufzeit, wenn man sich jedes Element einmal anguckt oder eine konstante Anzahl von Malen,
dann habe ich irgendwie zehnmal N als Laufzeit,
aber ich darf mir eben ein Element nicht en-mal angucken,
wenn ich mir jedes von En-Elementen N mal angucke,
damit ich nicht millinear bin,
nicht irgendwie quadratisch
Quadratisch, jedes Element mit jedem an einem Vergleichen,
höhere Polynome, sowas wie N hoch 3,
N hoch 4 und so, das wird schon seltener,
gibt es aber auch Algorithmen, die sowas haben.
Da muss ich dann so, sag mal,
machen wir jedes Element mit jedem Vergleichen und dann mit diesen Sachen nochmal mir irgendwie was angucken oder so,
also Pärchen bilden und nochmal was angucken oder so, hat man,
wie gesagt, eher selten bei Graf-Algorithmen werden wir ein Beispiel sehen,
ein anderes sehr bekanntes Beispiel ist Prim-Time-Test.
Genau, und exponentiell, wenn man jede Möglichkeit durchprobiert,
also exponentiell wäre sowas gewesen wie,
ich kriege eine Folge von Endzahlen und ich gucke mir einfach
sukzessive jede Anordnung davon an,
das sind dann irgendwie zwei Wochen oder exponentiell viele und dann gucke ich immer,
ob da was auf Tieres
bei rauskommt
Also alle Möglichkeiten durchprobieren, das sind meistens exponentiell.
Zusammenfassung für heute, dann sind wir auch gleich bei der Pause.
Das waren die Begriffe, die wir hatten, Datentyp,
Datenstruktur, Algorithmus. Und dann haben wir gesagt,
was uns jetzt interessiert, ist Zeit- und Platzkomplexität.
Und dann hatten wir diese drei wichtigen Punkte hier,
Definition für die Ohnnotation, wichtige Eigenschaften der Unnotation und wichtige Funktionen klassifizieren.
Also das ist so dieser Blog-Ohnnotation, der jetzt am Anfang kommt,
damit man sich später bei den Algorithmen wirklich gut darüber drüber unterhalten kann,
welche Laufzeit haben die,
ist das gut,
ist das schlecht
Und dann eben als Beispiele irgendwie lineare Suchen, Binäres suchen,
Maximum Sword, Insearchant Sword. Und das,
wo wir jetzt gleich in den nächsten 45 Minuten nochmal dann
einen Schwerpunkt hinlegen wollen, ist,
dass wir mit diesen Punkten nochmal mit der Unnotation dann nochmal ein bisschen arbeiten.
Und das sollte dann auch heute in den Übungen machen,
damit das eben gut sitzt. Und es ist auch so
die Erfahrung, dass das irgendwie ein bisschen problematisch ist so.
Und deswegen wollte ich mir da dann heute nochmal irgendwie die Zeit gönnen,
das zu machen. Und wenn er jetzt irgendwie sagt,
oh, das habe ich alles verstanden, das ist easy,
dann braucht ihr vielleicht gleich bei den nächsten 45 Minuten nicht dabei zu sein.
Aber ansonsten machen wir das gleich nochmal.
Und das sind die Themen der Vorlesung,
quasi das zweite Thema ist Zeit und Platzbedarf
von Algorithmen
zu untersuchen
Und die halt einzusortieren. Und die anderen Oberthemen der Vorlesung
sind eben erstens bekannte Algorithmen für Probleme kennenzulernen.
Damit man irgendwie, wenn man irgendwo sieht, so,
yo, das ist ein Quick-Sort oder so,
damit man grob weiß, was damit gemeint ist.
Und das dritte Thema ist eben,
eigene Algorithmen entwerfen zu können mit den Techniken,
die wir uns ansehen bei schon bekannten Algorithmen.
Das wollen wir machen. Gleich machen wir noch ein bisschen Unnotation.
Und nächstes Mal wollen wir uns mit sowas hier beschäftigen.
Der berechnet eigentlich auch nur die Fakultätsfunktion,
ist aber ganz grundlegend anders als die Sachen,
die wir uns bisher angeguckt haben,
weil hier so ein rekursiver Aufruf drin ist
Und bei dem Beispiel kann man jetzt noch sagen,
naja, okay, da kann ich mir trotzdem irgendwie vorstellen,
was ist der für eine schlimme Laufzeit haben oder was du für eine Laufzeit haben wird,
aber allgemein bei anderen rekusiven Algorithmen reichen unsere Techniken bisher noch nicht.
Also das, was jetzt so mit U-Notationen gemacht haben und irgendwie Aufrufe
in der Schleife zählen und so, das klappt halt bei rekusiven Algorithmen nicht.
Da gibt es andere Techniken, mit denen man das machen kann,
die gucken wir uns nächstes Mal an, nennt sich Rekurrenzgleichung,
dann werden wir uns, was ich heute noch überwiegend übersprungen habe,
mit der Korrektheit von Algorithmen beschäftigen.
Also warum klappt überhaupt dieser Insursion Sword so,
wie kann man das beweisen, Stichwort Schleifen in Varianten und so,
Genau, und dann werden wir in der Zukunft eben noch
ein bisschen weiter bei Suchen und Sortieren sein und uns spezielle Datenstrukturen anguckt,
mit denen man effizient sortieren kann.
Stichwort Heepsword und so. Und in der späteren Vorlesung machen wir
dann noch was mit Grafen und vielleicht Hashes und so.
Und genau. Fragen? Dann machen wir Pause bis 11
und treffen uns dann gleich wieder und machen nochmal 45 Minuten
ohne Notation