VAR p: link

Werbung
Skript zur Vorbereitung auf die Nebenfachs-Informatikprüfung bei Prof. Schweiggert
Stoff: VL Allg. Inf.I + II (mit Wiwis, etc., 2005/2006 VL bei Murmann)
Das folgende Skript hab ich zwei Tage vor meiner Prüfung als kleine Zusammenfassung
und Übung für mich selbst geschrieben. Deshalb ist das Skript auch nicht perfekt,
sachliche Fehler sind möglich und wahrscheinlich, neben Rechtschreibfehlern und
schlechtem Satzbau…..
aber das wird euch wahrscheinlich herzlich egal sein : )
wenn ihr das könnt, was im skript steht, dann steht der 1,0 nichts mehr im Wege.
Viel Erfolg damit,
SirTobi
Thematik: Sortierverfahren:
Sortierung von Daten ist sehr wichtig und beansprucht etwa 25% der Rechnerzeit.
Man beschränkt sich dabei immer auf Sortierung von Zahlen durch Größenvergleiche, da sich
auch andere Datensätze als reine Zahlen indir. dadurch ausdrücken lassen.
Generell wird unterschieden zwischen internem und externem Sortieren. Beim internen
liegen alle Datensätze wie in einem Array zu jedem Zeitpunkt zugreifbar zur Verfügung. Es
kann theoretisch mit jedem Feld begonnen werden. Externes kann man sich als Sortieren mit
Hilfe von Stacks vorstellen, bei denen nur immer jeweils das oberste Element sichtbar ist, und
vom Stapel genommen werden kann.
Es existieren einige verschiedene Sortieralgorithmen die rein iterativ oder auch rekursiv
funktionieren. Je nach Anwendung eignet sich mal der eine, mal der andere Algorithmus
besser. Zuerst zu den rekursiven.
Sie sind daher rekursiv da die zu sortierenden Datensätze immer auch ein bestimmte Art und
Weise durch die gleiche Funktion aufgeteilt und die selben Befehle auf en Teildatensatz neu
angewandt werden, es sind endliche Rekursionstiefen möglich. Hier gibt es Quicksort,
Mergesort und Heapsort. Es gilt, dass alle Sortierverfahren (auch sämtliche iterativen), bis auf
Mergesort, in-Place/in-situ arbeiten. Das bedeutet, dass während des Sortiervorgangs kein
weiterer Speicherplatz benötigt wird als die Datensätze einnehmen.
Die rekursiven Verfahren besitzen alle im Regelfall nach Landau-Notation die
Zeitkomplexität O(nlogn). Kurz zur Landau Notation: sie gibt an wie viel relative Rechenzeit
für einen Algorithmus/Funktion/Prozedur benötigt wird. Sie kann Konstant sein,
Logarithmisch, Linear, Polynomial und Exponentiell.
Quicksort benötigt im schlechtesten Fall O(n²). Es beruht auf dem Divide-et-Impera /
Command-and-Conquer  Ansatz, nach dem ein Teilproblem immer weiter aufgeteilt wird,
bis die Teillösungen trivial sind und wieder zusammengesetzt werden können.
Als Pivot-Element wäre der echte Median die beste Wahl, dies ist aber nur in schon sortierten
Listen möglich, folglich muss eine Alternative gewählt werden. Die Wahl des ersten Elements
garantiert die Termination, erhöht aber die Worst-Case Wahrscheinlichkeit. Das letzte
Element endet in einer Endlosschleife wenn es das größte Element im Array ist. Ein gute
Wahl ist der Median aus erstem, mittlerem und letztem Element. Die Hilfsvariablen i und j
setzen jeweils von links und rechts außen am Array an. i wandert solange nach rechts bis es
ein Element größer oder gleich dem Pivot entdeckt. j nach links, bis es eines kleiner oder
gleich dem Pivot entdeckt. Dann erfolgt der Austausch dieser beiden Elemente. I und j
bewegen sich nach dem gleichen Prinzip weiter bis sie zusammentreffen und i >= j, bzw. i
und j auf einem Element sitzen. Dort wird dann das Array in zwei Teile aufgeteilt, also
entweder genau zwischen i und j oder rechts davon, wenn sie aufeinander liegen. So wird nun
mit den Teildatensätzen weiter verfahren, bis alle Daten geordnet sind und sie
zusammengefügt werden können. Quicksort arbeitet nicht stabil, d.h. Datensätze mit gleich
großem Schlüsselelement können vertauscht werden. Dies ist problematisch, wenn
nacheinander nach mehreren verschiedenen Schlüsseln sortiert wird. Instabil sind außerdem
Heapsort und Selectionsort. Die restlichen Algorithmen sind alle stabil.
Heapsort (in-Place/ O(nlogn)/ Instabil) basiert auf einem als Binär-Baum (Heap/Halde)
behandelten Array. Die Indizes des Array werden so in einen Baum übertragen, dass das
Element i die Kinder 2i und 2i +1 besitzt. Die Wurzel ist also das Feld mit Index 1, dessen
Kinder 2 und 3, usw. es werden also nach Level-Order von links nach rechts die Daten in den
Baum übertragen. Man beginnt nun mit dem Teilbaum, der den höchstwertigen Index besitzt,
also „den zuletzt gefüllten“, und vertauscht den Elternknoten, falls der Schlüsselwert kleiner
ist als eines oder beide seiner Kinder, mit dem größeren der Kinder. So fährt man fort und
geht die Indizes rückwärts bis zu Index 1 (Wurzel). Man muss dabei allerdings darauf achten
den Baum immer wieder zu aktualisieren, d.h. wenn ganz oben etwas vertauscht wird, dies
sich auch auf schon einmal geordnete Knoten auswirken kann. Dieses Ordnen bewirkt ein
Versickern der kleineren Werte nach unten. Ist der Heap fertig geordnet, wird damit
begonnen die Wurzel mit dem größten Index zu tauschen und diesen letzen Knoten zu
löschen und den Inhalt in jenem Indexfeld zu speichern. (Größter Indexwert: größter
Schlüsselwert). Danach muss der Baum durch versickern, so wie vorher, wieder geordnet
werden. Dann wird der nächst kleinere Indexknoten entfernt und so fortgefahren bis der Array
komplett geordnet ist.
Mergesort (nicht in-Place, Stabil, O(nlogn) zeichnet sich durch eine durchgehend gleich
bleibende Zeitkomplexität aus und ist gut zum Ordnen verketteter Listen geeignet. Es läuft
ebenso nach dem Divide-and-Conquer Prinzip ab und ist stabil. Dabei wird der Array immer
weiter aufgeteilt bis ein-feldige Elemente vorliegen, die als geordnet gelten. Die Einzelfelder
werden nun entsprechend ihrer Schlüsselwertgrößen Stück für Stück auf demselben Weg
rückwärts zusammengesetzt. Es entsteht ein geordneter Array. Nachteilig ist allerdings der
zusätzlich notwendige Speicherplatz zur Zwischenspeicherung.
Soviel zu den rekursiven und wohl auch grundsätzlich interessanteren Sortiermethoden.
Bei den iterativen gibt es Selectionsort, Insertionsort und seine Weiterentwicklung Shellsort,
Bubblesort und den bidirektionalen Bubblesort, auch Shakersort genannt. Omikron beläuft
sich immer auf O(n²) außer bei Shellsort, welches eine geringere Zeitkomplexität von ca. n 1,25
besitzt.
Selectionsort (instabil, O(n²), in-Place) durchläuft das Array linear und sucht das kleinste
Element, welches dann mit dem Element auf Indexfeld 1 vertauscht wird. Dann sucht es das
zweitgrößte, welches auf Feld 2 kommt, usw..
Insertionsort
(stabil, O(n²), in-Place) durchläuft das Array, sucht das Kleinste
Schlüsselelement und schiebt es an die Stelle des ersten Feldes. Die nachfolgenden Felder
bis zum gewählten Feld, müssen also alle um eines verschoben werden. Dann das
zweitkleinste an die zweite Stelle, wiederum verschieben des Restes, usw.. Eine
Weiterentwicklung ist Shellsort (in-Place/Stabil/O(n1,25). Dabei wird eine ungeordnete
Sequenz in eine zweidim. Matrix übertragen, die nun Spaltenweise mittels Insertionsort
geordnet wird. Dann wird die Matrix in eine weitere Matrix übertragen die kürzere
Zeilenlänge aufweist. Deren Spalten werden auf ein Neues mit Insertionsort geordnet. Am
Schluss liegt wieder eine eindimensionale Sequenz vor, die ein letztes Mal mit Insertionsort
geordnet wird. Von den iterativen Sortiermethoden ist dies die schnellste (siehe oben) obwohl
der mathematische Beweis schwierig ausfällt.
Bubblesort (stabil/in-place/O(n²) ist ein recht naiver Algorithmus der selten benutzt wird. Er
basiert auf paarweisem Vergleich von Schlüsselwerten im Array, bei dem die Elemente so
vertauscht werden, dass die schwereren (höherwertigeren) Elemente nach rechts blubbern, bis
es auf ein größeres Element stößt, welches dann weiter nach rechts verblubbert wird.
Eine weitere Möglichkeit ist Shakersort, bzw. der bidirektionale Bubblesort. Der erste
Schritt ist wie bei Bubblesort. Ist man dann am rechten Rand angekommen geht man von dort
nach links, wobei man nun die kleinsten Elemete nach der äquivalenten Regel nach links
vertauscht. So wandert man nun hin und her bis der Array geordnet ist.
Ein Geschwindigkeitsvergleich ergibt, dass Shellsort schneller als die anderen iterativen
Algorithmen läuft.
Bei unsortierten sowie vorsortierten Daten (was im Rechner viel häufiger vorkommt/nur
leichte Veränderungen im Datensatz) zeigt sich folgende Reihenfolge, beginnend mit dem
Schnellsten: Quicksort, Mergesort, Heapsort
Bei unsortierten Datensätzen ist Bubblesort von den iterativen der langsamste, allerdings bei
vorsortierten Sätzen der Schnellste (abgesehen von Shellsort).
Thematik Bäume:
Bäume sind eine wichtige Struktur in der Informatik um Daten zu organisieren, zu speichern
und wieder zu finden. Es existieren mehre Definitionen.
-Bäume sind spezielle, gerichtete, zusammenhängende Graphen.
-Rekursive Def.: Ein Baum ist leer oder hat einen Wurzel die mit weiteren disjunkten (nicht
gleichen, nicht überschneidenden) Bäumen über Kanten verbunden ist.
Weitere Eigenschaften eines Baumes:
-jeder Knoten hat nur eine eingehende Kante, es sind keien Zyklen erlaubt,
Höhenbalanciertheit: Die Pfadlänge (von Wurzel zu beliebigem Blatt) innerhalb eines
Baumes darf sich nicht um mehr als 1 (oder je nach gewähltem Wert) unterscheiden.
Gewichtsbalanciertheit (auch vollständig balanciert genannt): Die Anzahl der Kinder eines
Knotens differiert um nicht mehr als 1 vom Grad des Baumes.
Der Grad bezeichnet die Anzahl der Kinder die ein Knoten hat. So ist ein Binärbaum vom
Grad zwei. Die Höhe hat in der Wurzel den Wert 0, und nimmt in jeder Generation um eins
zu. Die Anzahl der inneren Konten eines Binärbaums lässt sich mit der Formel 2h-2
berechnen, die Anzahl der Blätter mit 2h.
Bei einem geordneten Baum sind die in den Knoten und Blättern gespeicherten Werte nach
der Größe geordnet. Bei einem orientierten Baum nicht (Darstellung durch geschachtelte
Mengen möglich).
Bäume werden zur Datenorganisation z.B. auch in Betriebssystemen eingesetzt, so ist das
Dateisystem von Unix ein Vielwegbaum. Weiterhin ist auch der Ascii-Code als Baum
festgelegt in dem nur die Blätter die Informationen/die Ascii-Symbole tragen und die Knoten
nur den Weg über 0 und 1 weisen. Dies entspricht einem Blattsuchbaum. Auch spielen bei der
Datenkomprimierung etwa von Textdateien Bäume eine Rolle. Man nutzt dabei HuffmanBäume in denen die Buchstaben eines Alphabets der Wahrscheinlichkeit ihres Vorkommens
nach in den Knoten und Blättern gespeichert sind.
Es gibt verschiedene Weisen/Notationen einen Baum mit Daten zu füllen, bzw. sie
auszulesen/ zu traversieren.
Infix: links, Wurzel, rechts Präfix: Wurzel, links, rechts Postfix: links, rechts, Wurzel,
Diese Weisen sind rekursiv zu verstehen und werden bei Traversierung nicht mit –fix sondern
mit -order benannt.
Postorder ist von Maschinen leichter zu verarbeiten. Der Shunting-Yard-Algorithmus kann
Infix-Notationen in Postfix umwandeln (läuft über Stack).
Nun einige Modula 2/programmierrelevante Informationen. Bäume können als ADT
aufgefasst werden. Die übliche Implementation läuft über Zeiger:
TYPE pBaum = POINTER TO Baum
Baum = RECORD
key : INTEGER;
left, right: pBaum;
END;
Eine Prozedur die alle Knoten eines Baums zählt könnte folgendermaßen aussehen:
PROCEDURE zaehlen (b: pBaum; VAR zaehler: CARDINAL)
BEGIN
IF b <> NIL THEN
zaehlen (b^.left, zaehler);
zaehlen (b^.right, zaehler);
INC (zaehler);
END zaehlen;
Aufruf durch:
Y:=0;
Zaehlen (x,y);
C:=Y ( hier ist dann der zaehlerwert drin)
Oder auch:
PROCEDURE visit (b: pBaum; VAR: zaehler: INTEGER);
BEGIN
visit (b^.left);
zaehler := zaehler + 1;
visit (b^.right);
END visit;
Auslesen würde genauso funktionieren: Reihenfolge kann als In-Order, Pre-Order oder PostOrder gewählt werden.
PROCEDURE traversiere (b: pBaum);
BEGIN
IF b <> NIL THEN
In-Order:
Traversiere (b^.left); WriteInt (b^.key); traversiere (b^.right);
Pre-Order: WriteInt (b^.key); traversiere (b^.left); traversiere (b^.right);
Post-Order: traversiere (b^.left); traversiere (b^.right); WriteInt (b^.key);
END traversiere;
Suchen eines bestimmten Elementes w im Baum:
PROCEDURE suche (w:INTEGER; b: pBaum): BOOLEAN
BEGIN
IF b =NIL THEN RETURN FALSE
IF w = b^.key THEN RETURN TRUE;
ELSIF w < b^.key THEN RETURN suche(w, b^.left);
ELSE RETURN suche (w,b^.right);
END suche;
Eine Prozedur die einen Binärbaum auf Vollständigkeit überprüft kann mittels zweier
Prozeduren realisiert werden.
PROCEDURE count (b:pBaum) : INTEGER
BEGIN
IF b=0 THEN RETURN 0
ELSE RETURN 1 + count(b^.left) + count(b^.right);
END;
END count;
PROCEDURE test(b:pBaum): BOOLEAN
BEGIN
RETURN count(b^.left)=count(b^.right);
END test;
ADT Stack und Queue:
Da sie ADTs sind, sind sie implementierungsunabhängig. Es ist also für den Benutzer nicht
von Belang, ob sie über spezielle Arrays oder über Zeiger erstellt werden.
Stack: Hier greift das Prinzip: Last In, First Out. LIFO. Man nennt Stacks auch Stapel, bzw.
Kellerspeicher.
Die zentralen Operationen in einem Stack sind: Stack leer?, Stack voll?, push, pop, top.
Queue: First In, First Out, FIFO
Zentrale Operationen: Queue leer?, Queue voll? Push am Ende, Pop am Anfang,
Meist wird eine Implementierung über verkettete Listen gewählt. Diese können einfach oder
doppelt verkettet sein.+-
Zählen der Listenelemente, einfach verkettet:
PROCEDURE zaehlliste (l:link): INTEGER
BEGIN
IF l = NIL THEN RETURN 0
ELSE RETURN 1 + zaehlliste(l^.next);
END
END zaehlliste;
C := zaehlliste (b);
Rekursive Prozedur zum Anhängen von Elementen hinten an der Liste:
PROCEDURE enqeueue (zahl: INTEGER; VAR liste: pListe );
BEGIN
IF liste = NIL THEN
liste^.key := zahl;
liste^.next := NIL;
ELSE enqueue (zahl, liste^.next);
END
END enqueue;
Einfügen Vorne in Liste
PROCEDURE vorne (zahl: INTEGER; kopf: link)
VAR p: link
BEGIN
P^.key := zahl;
P^.next := kopf;
Kopf := p;
END vorne;
Doppelt verkettete Listen sind geeignet für Datensequenzen, die von beiden Seiten gelesen
werden können sollen. (4 verben am ende eines satzes, das gibt’s nur im deutschen  )
So wie z.B. lange Zahlen.
Hashing:
Hash-tabellen werden erstellt wenn Datenbanken geschaffen werden sollen.
Dabei ist die Zeitkomplexität im Idealfall O(1). Einer Reihe von Datensätzen wird durch eine
Hash-Funktion ein bestimmter Platz in einem Array zugewiesen. Die Funktion wird benötigt
wenn die Daten darauf verteilt werden und wenn sie beim Zugriff wieder gefunden werden
müssen. Die Daten werden auf dem Array gestreut, in gewisser Weise zufällig zueinander.
Bei der Reservierung des Speicherplatzes sollte beachtet werden, dass die Tabelle platzmäßig
nur zu 80% mit allen Daten gefüllt ist. Eine Hash-Funktion liefert im Idealfall keine
Kollisionen. Um dem zu entgegnen, gibt es zwei Stragtegien die dies verhindern. Einerseits
besteht die Möglichkeit den Array mit Zeigern zu füllen, die im Fall einer Kollosion einfach
den zusätzlichen Datensatz an den jeweiligen Zeiger anhängen und somit eine Liste entsteht.
Die andere Möglichkeit ist lineare Sondierung zu benutzen, wobei bei einem durch die
Hash-Funktion zugewiesenen aber belegten Speicherplatz einfach im Array abwärts gerutscht
wird, bis ein freies Feld entdeckt wird, welches dann gefüllt wird.
Beim Hashing kann eine theoretisch unendliche Quellmenge auf den Wertebereich der
Hashfunktion reduziert werden. Die Hashfunktion sollte einfach zu berechnen sein und
trotzdem möglichst keine Kollisionen erzeugen.
Mustersuche
Wenn man in einem Text ein Wort, also eine bestimmte Abfolge von Buchstaben finden will
kann einfach linear die Sequenz durchgehen und solange nach der Abfolge suchen bis sie
entdeckt wurde (Brute-Force-Ansatz). Falls aber Teile des Wortes schon vorkommen kann
man die Informationen dieses Mismatch nutzen, mitzählen und dann die entsprechenden
Abstände weiterspringen (Knuth-Morris-Pratt-Algorithmus).
Dateien in UNIX
Unter Unix gibt es drei zu unterscheidende Dateitypen.
Es gibt:
Reguläre Dateien: Binäre Daten, Texte, Software, etc.
Dateiverzeichnisse/Katalogdateien: enthalten Inode-Listen, Verweise auf Speicherort
Spezielle Dateien/Gerätedateien: sind zuständig für Einbindung der Hardware, stehen für
die Geräte
Inode:
Index-Node: 128 byte große spezielle Datenstruktur die einer Datei zugehörig ist und Daten
über diese Datei enthält
Speichert Typ, Größe, Datum, Besitzer, Zugriffsrechte, etc., sowie Verweise auf die
Cluster in Speicher wo sich eigentliche Datei befindet. Kleine Dateien können direkt in der
Inode gespeichert werden, sehr große enthalten in ihren ersten Clustern nochmals Verweise
auf weitere Cluster.
Sprache
In einer Sprache existieren Zeichen, die Elemente eines Alphabets sind. Ihre
Aneinandereihung zu Worten und Sätzen wird durch die Syntax geregelt. Die Interpretation
und Wirkung der Zeichenfolgen, z.B. durch einen Rechner wird durch die Semantik
übernommen.
Die Grammatik ist ein 4-er Tupel, welches Produktionsregeln, Terminalzeichen,
Nichtterminalzeichen und das Startsymbol enthält.
EBNF (Erweiterte-Backus-Naur-Form) ist eine Metasprache, mit der man die
Produktionsregeln vereinfacht und nach bestimmten Regeln darstellen kann. Sie benutzt zur
Gliederung und Darstellung von Möglichkeiten die Symbole [ ]. Option, {} Null bis beliebig
oft, | oder, ( ) Klammerung.
Der Komplexitätsgrad einer Sprache wird durch die Chomsky-Hierarchie angegeben. Sie
werden von verschiedenen Automaten erkannt.
Typ 0: Grammatik ohne Einschränkungen, Turingmaschine,
Typ 1: mit Einschränkungen, abgewandelt Turingm.
Typ 2: kontextfrei, Kellerautomat, sind durch EBNF darstellbar
Typ 3: reguläre Gram., DEA, sind durch EBNF darstellbar
Ein Wort ist Teil der Sprache, wenn damit ein Terminalzustand erreicht wird.
Ist Wort Teil der Sprache? (bottom up, Top down)
Ein regulärer Ausdruck ist eine Terminalzeichenfolge die von einem Automat erkannt wird.
Bei Textersetzungen, Suchen in Editoren.
Die Befehle in UNIX können gemeinsam mit regulären Ausdrücken vorkommen.
Jede durch einen endlichen Automaten erkannte Sprache ist regulär.
Datentypen
Es wird zwischen drei großen Datentypengruppen unterschieden.
Einerseits einfache Datentypen (Gleitkommazahlen, Boolean, Interger, Char, Enumeration,
Subrange,etc.), strukturierte Datentypen (Arrays, Record, Sets) und dynamische
Datentypen (Zeiger).
Einfach Datentypen:
Boolean: belegt ein Bit, hat keinen Wertebereich, nimmt nur TRUE oder FALSE an,
Operatoren sind NOT, AND, OR (in der Mächtigkeit der Abfolge), es sind die üblichen
Vergleiche möglich.
Char: Darstellung von Zeichen im Rechner, basiert auf ASCII (american standard code for
information interchange), ASCII hat 7 bit (es gibt abwandlungen mit 8 bit um alle
Sonderzeichen einer Landessprache auszudrücken). Das 8 Bit wurde auch genutzt um zu
überprüfen ob die Gesamtfolge der Bits eine gerade Zahl ergibt, um die Fehlerquote bei
Datenübertragungen im Auge zu behalten. Neuerdings findet allerdings ein Umstieg auf
Unicode statt, bei dem es auch div. Untertypen gibt. Am gebräuchlichsten ist die Darstellung
durch UTF-8 (Unicode Transformation Standard): der von 1 Byte (beinhaltet normalen
ASCII) bis zu 6 Byte reicht. Damit können alle Schriftzeichen die es auf der Welt gibt
dargestellt werden. Jedem ASCII Symbol ist ein Ordinalwert zugeordnet der durch den Befehl
ORD(symbol) erhalten werden kann. Umgekehrt erhält man das ASCII-Symbol nach Eingabe
der Ordinals mittels CHR(ASCII-Code).
Integer: Wertebereich der ganzzahligen negativen und positven Zahlen,
die Untertypen Byte stellen 8bit zur Verfügung, ShortInt 16 bit, Integer standardmäßig 32 bit,
und LongInt 64 bit, wobei es immer auf das Rechnersystem ankommt mit dem man arbeitet.
Da in einem Rechner nur ein Addierwerk existiert müssen auch Subtraktion dadurch
dargestellt werden. Problematisch ist also die rechnerinterne Darstellung negativer Zahlen.
Dies wird gelöst durch das Zweier-Komplement. Hierbei wird zunächst eine positive Zahl
stellenweise invertiert und ein letztes Bit addiert. Das erste bit stellt dabei sozusagen die
negativen –128 dar (bei 8 bit) und die restlichen mit eins besetzten Stellen, die Werte die zur
–128 addiert werden müssen.
Operationen sind also Addition, Subtraktion, DIV mit Rest, MOD, Multiplikation und
Vergleiche.
-MAXINT und MAXINT begrenzen den abgedeckten Zahlenbereich.
Cardinal: zur Darstellung positiver ganzzahliger Zahlen, gibt es in manchen System schon
gar nicht mehr. Übliche Operationen möglich,
Real: Gleitkommazahlen die nicht den mathematischen reellen und rationalen Zahlen
entsprechen, da der Speicherbereich endlich ist. Folglich ist es nur eine Näherung, deren
Genauigkeit von der Größe des Exponenten und er Mantisse abhängig. Shortreal besetzt bei
der 32 Bit-Wortlänge, ein Bit mit dem Vorzeichen, 8 Bit mit dem Exponenten und 23 Bits mit
der Mantisse. Longreal mit 64 Bit Wortlänge ebenso ein Bit mit dem Vorzeichen, 11 Bit mit
dem Exponent und 52 Bit mit der Mantisse.
Der Bereich um 0 kann nicht exakt dargestellt werden und wird als 0 interpretiert. Dies kann
als Zwischenergebnis zu Problemen führen. (negative und positive Underflow).
Bereichsüberschreitungen werden auch bei Integer durch Overflowbit angezeigt. Die
Genauigkeit ist im Kleinen groß, und nimmt mit der Größe der Zahl ab (endlicher
Speicherbereich).
Für arithmetische Berechnung gibt es spezielle Prozessoren. Deren Leistung wird in FLOPS
(Floating Point Operations Per Second) angegeben. Also die Anzahl der Additionen oder
Multiplikationen die in einer Sekunde bewältigt werden können.
Die Einheit MIPS (Million Instructions Per Second) gibt an, wie viele Maschinenbefehle in
der Sekunde eingelesen werden können. 1 MIPS bedeutet, er kann eine Million
Maschinenbefehle pro Sekunde ausführen.
Strukturierte Datentypen:
Array: Speichert gleichartige Daten in einem linearen Speicher, mehrdimensionale Arrays
enthalten in ihren Feldern ebenfalls weitere Arrays. Je nach Schachtelung viele Dimensionen
möglich.
Record: Speicherung verschiedenartiger Daten
Dynamische Datentypen:
Zeiger: Daten werden über anonyme Adressen indirekt angesprochen, er enthält nur einen
Verweis (die Adresse) auf die eigentlich Datei. Es gibt keinen Index und die Speicherbereiche
müssen nicht zusammenhängend sein.
Die Lebensdauer ist unbestimmt.. Bsp. Liste: je nach Aktion wächst oder schrumpft die Liste
dynamisch, die einzelnen Zeiger werden alloziert oder dealloziert.
Rekursion
Rekursion ist ein nicht nur in der Informatik existentes Phänomen.
Grundsätzlich ist damit eine Erscheinung gemeint, die immer wieder durch die selben Schritte
auf sich bezogen entsteht. Bspw. Ein math. Funktion die sich selbst enthält (z.B. FibonacciReihe: f(n)= f(n-1)+f(n-2)), eine Prozedur die sich selbst aufruft oder Muster die immer
wieder auf die Teile des bestehenden Musters gesetzt werden (Fraktale, Pythagorasbaum,
Mandelbrotmenge, Küstenlinien, Populationsdynamik Blattinduktion mit Fibonacci,
Attraktoren mit Oszillation um Grenzwert, Wasserstrudel, etc.). Auch gibt es rekursive
Definitionen (siehe Baumdefinition). Zur Rekursion in der Informatik.
Sie spielt dort vor allem eine Rolle bei Prozeduraufrufen. Als dir. Rekursion wird es
angesehen, wenn eine Prozedur während ihres Aufrufs sich selbst nochmals aufruft.
Indirekte/verschränkte Rekursion nennt man den Zustand bei dem eine Prozedur A eine
Prozedur B aufruft, die wiederum A aufruft.
Eine einfach rekursive (Funktions-)Prozedur, die die Fakultät einer Zahl ausgibt ist folgende:
PROCEDURE fakult (x:INTEGER):INTEGER
BEGIN
IF x=0 THEN RETURN 1
ELSE RETURN x*fakult(x-1);
END fakult;
Es ist wichtig bei rekursiven Prozeduren eine Abbruchbedingung mitanzugeben, da sonst die
Gefahr von Endlosschleifen droht. Dies wird durch den Trivial/Basis-Fall gehandhabt.
Es existieren immer eine Abbruchbedingung und ein Rekursionszweig.
Rekursive Implementierungen sind meist eleganter, kürzer und einfacher als iterative
Implementierungen. Sie sind aber auch meist etwas langsamer und brauchen mehr Speicher.
Es gibt einige Untertypen von Rekursion:
Lineare Rekursion: bei der in jedem Zweig höchstens ein Selbstaufruf stattfindet. (fakultät)
Eine Lineare Rekursion ist dann eine Repetitive/tail-Rekursion: wenn der Aufruf
am Ende erfolgt, kann durch eine Schleife ersetzt werden. Sodass anstatt neuer Inkarnationen,
Variablen wiederverwendet werden, dies spart Speicherplatz.
Kaskadenartige/baumartige Rekursionen: sie sind nicht linear, und es kommt in den
Aufrufzweigen zu mehr als einem Aufruf (Fibonacci).
Geschachtelte Rekursion: z.B.: f(n)=f(n+1) oder so...
(so, jetzt hab ich keine Lust mehr)
Prozeduren
Wichtige Stichworte zu Prozeduren:
Normale und Funktionsprozeduren, direkter Aufruf, Aufruf als Teil von Ausdruck,
Resulttype, Ergebniswert, Call-by-value, Call-by-reference, aktuelle und formale Parameter,
Substitution, Seiteneffekte, globale Variablen,
Herunterladen