- 1 Section
- 10 Lessons
- unbegrenzt
- Algorithmen & Datenstrukturen10
- 1.1Was ist ein Algorithmus?
- 1.2Struktogramm (Nassi-Shneidermann)
- 1.3Pseudocode schreiben
- 1.4Kontrollstrukturen: Sequenz, Auswahl, Schleife
- 1.5Rekursion verstehen
- 1.6Suchen: linear vs. binär
- 1.7Sortieren: Bubble, Selection, Insertion, Merge
- 1.8O-Notation: Zeitkomplexität
- 1.9Datenstrukturen: Array, Liste, Stack, Queue, Baum, Hash
- 1.10Algorithmik-Aufgaben
Kontrollstrukturen: Sequenz, Auswahl, Schleife
In den vorigen Lektionen haben wir Struktogramme und Pseudocode als Darstellungsformen kennengelernt. Beide nutzen die gleichen Grundbausteine: Kontrollstrukturen. Diese bestimmen, in welcher Reihenfolge und unter welchen Bedingungen Anweisungen ausgeführt werden. Ohne Kontrollstrukturen wäre ein Programm eine lineare Abfolge von Anweisungen ohne Logik.
Das verblüffende Resultat eines Theorems aus den 1960ern (das Strukturtheorem von Böhm-Jacopini): jeder Algorithmus, der überhaupt berechenbar ist, lässt sich allein mit drei Kontrollstrukturen ausdrücken – Sequenz, Auswahl und Schleife. Mehr braucht es nicht. Diese drei Strukturen sind das Fundament der strukturierten Programmierung und der zentrale Inhalt dieser Lektion.
1) Die drei Grundstrukturen
Bevor wir in Details gehen, der Überblick. Die drei Kontrollstrukturen entsprechen drei verschiedenen Wegen, wie der Programmablauf gesteuert wird:
2) Sequenz – das Einfachste
Die Sequenz ist die simpelste Kontrollstruktur: Anweisungen werden in der Reihenfolge ausgeführt, in der sie geschrieben sind. Anweisung 1, dann Anweisung 2, dann Anweisung 3. Keine Verzweigung, keine Wiederholung. Das entspricht dem linearen Programmablauf.
a = 5
b = 3
summe = a + b
GIB AUS summe // 8
Klingt trivial – ist es auch. Aber bemerkenswert ist: die Reihenfolge spielt eine Rolle. Wenn du die Zeilen vertauschst (z.B. summe = a + b vor a = 5), ist das Ergebnis falsch oder gar nicht definiert. Im Code zu denken heißt von Anfang an, in Sequenzen zu denken.
3) Auswahl (Selektion) – Entscheidungen treffen
Die Auswahl – auch Selektion oder Verzweigung genannt – führt einen anderen Code-Block aus, je nachdem ob eine Bedingung wahr oder falsch ist. Im Pseudocode mit WENN ... DANN ... SONST, im Code als if/else. Die Bedingung ist ein Boolescher Ausdruck – entweder wahr oder falsch.
WENN note <= 4 DANN ... SONST .... Bei jedem Wert wird die Bedingung neu geprüft, und der richtige Zweig läuft. Das SONST ist übrigens optional – wenn nur eine Aktion bei wahr gemacht werden soll, kann man es weglassen.4) Mehrfachverzweigung – mehr als zwei Zweige
Manchmal reicht ein einfaches if/else nicht. Du willst zwischen drei, vier, fünf Fällen unterscheiden. Dafür gibt es zwei Lösungen: die verkettete Mehrfachverzweigung (else if) oder die case-Anweisung (switch).
WENN note = 1 DANN
GIB AUS "sehr gut"
SONST WENN note = 2 DANN
GIB AUS "gut"
SONST WENN note = 3 DANN
GIB AUS "befriedigend"
SONST
GIB AUS "nicht so toll"
ENDE WENN
// Variante 2: Case-Anweisung (kompakter bei vielen Fällen)
FALLUNTERSCHEIDUNG note
FALL 1: GIB AUS "sehr gut"
FALL 2: GIB AUS "gut"
FALL 3: GIB AUS "befriedigend"
SONST: GIB AUS "nicht so toll"
ENDE FALLUNTERSCHEIDUNG
Beide Varianten sind funktional gleichwertig. Wenn du gegen einen einzigen Wert auf verschiedene konkrete Werte prüfst, ist die case-Anweisung übersichtlicher. Wenn die Bedingungen komplexer werden („Note < 2 UND Bonuspunkte ≥ 10"), bist du auf verkettete if/else angewiesen.
5) Schleifen (Iteration) – Wiederholungen
Die dritte und mächtigste Kontrollstruktur ist die Schleife. Sie wiederholt einen Code-Block. Dabei gibt es verschiedene Schleifenarten, die sich darin unterscheiden, wann die Abbruchbedingung geprüft wird und wie der Zähler gesteuert wird:
x = x * 2
ENDE SOLANGE
eingabe = lese()
BIS eingabe = 0
GIB AUS i
ENDE FÜR
GIB AUS x
ENDE FÜR
6) Schleife im Detail: Schritt-für-Schritt
Schleifen sind für Anfänger oft die schwierigste Kontrollstruktur. Es hilft, eine Schleife einmal Schritt für Schritt durchzulaufen und zu beobachten, wie sich Variablen ändern und wann die Bedingung schaltet. Klick „Schritt":
summe = 0
SOLANGE x <= 5 TUE
summe = summe + x
x = x + 1
ENDE SOLANGE
GIB AUS summe
x wird in jedem Durchlauf um 1 erhöht. summe akkumuliert die Werte. Vor jedem Durchlauf wird die Bedingung x <= 5 geprüft – wenn sie falsch wird (also x = 6), wird die Schleife verlassen und es geht mit der nächsten Zeile weiter. Am Ende steht summe = 1+2+3+4+5 = 15. Wichtig: wäre die Zeile x = x + 1 vergessen, würde die Bedingung nie falsch werden – Endlosschleife!7) Verschachtelung – die Macht der Kombination
Wirklich spannend werden Kontrollstrukturen, wenn man sie kombiniert und verschachtelt. Eine Schleife in einer Verzweigung, eine Verzweigung in einer Schleife, eine Schleife in einer Schleife. Damit lassen sich komplexe Probleme lösen. Beispiel: alle Primzahlen bis 50 finden:
FÜR n VON 2 BIS 50
istPrim = wahr
// Innere Schleife: alle möglichen Teiler prüfen
FÜR i VON 2 BIS n - 1
// Verzweigung: teilbar?
WENN n mod i = 0 DANN
istPrim = falsch
ENDE WENN
ENDE FÜR
// Verzweigung: Primzahl ausgeben?
WENN istPrim DANN
GIB AUS n
ENDE WENN
ENDE FÜR
Was siehst du hier? Eine Sequenz (oben nach unten), in der eine Schleife steckt, in der eine weitere Schleife steckt, in der eine Verzweigung steckt – und nach der inneren Schleife wieder eine Verzweigung. Die drei Grundbausteine werden hier alle benutzt und mehrfach kombiniert. Das ist „echte" Programmierung.
8) Sprunganweisungen: break und continue
In der „reinen" strukturierten Programmierung gibt es nur die drei Grundstrukturen. In der Praxis erlauben fast alle Programmiersprachen zusätzlich zwei „Sprunganweisungen" innerhalb von Schleifen:
- break: bricht die aktuelle Schleife sofort ab. Der Code nach der Schleife wird normal weiter ausgeführt.
- continue: überspringt den Rest des aktuellen Durchlaufs und geht zur nächsten Iteration (also zurück zur Bedingung).
Diese sind sehr praktisch – aber sparsam verwenden. Sie machen den Code-Fluss weniger linear und schwerer nachvollziehbar. Eine while-Schleife mit klarer Bedingung ist meist sauberer als eine endlose Schleife mit innerem break.
FÜR JEDES x IN liste
WENN x = ziel DANN
GIB AUS "gefunden!"
VERLASSE // break
ENDE WENN
ENDE FÜR
// continue: ungerade Zahlen überspringen
FÜR i VON 1 BIS 10
WENN i mod 2 ≠ 0 DANN
NÄCHSTER // continue
ENDE WENN
GIB AUS i
ENDE FÜR
// → gibt 2, 4, 6, 8, 10 aus
9) Häufige Fehler bei Kontrollstrukturen
Drei sehr klassische Stolperfallen, die jeder Programmieranfänger mindestens einmal erlebt:
SOLANGE x > 0 ohne dass x dekrementiert wird. Programm hängt sich auf. Lösung: prüfen, ob die Zustandsänderung im Schleifenrumpf passiert.FÜR i VON 1 BIS n vs. FÜR i VON 0 BIS n-1. Bei Arrays mit 0-basiertem Index läuft die erste Variante in einen Out-of-bounds-Fehler.= ist Zuweisung, == ist Vergleich. Klassiker: if (x = 5) setzt x auf 5 statt zu vergleichen. Im Pseudocode meist beides als = – beim Übersetzen aufpassen.summe müssen vor der Schleife auf 0 gesetzt werden. Sonst undefiniert oder Vorgängerwert. Pseudocode-typisch: summe = 0 direkt über die Schleife schreiben.SOLANGE NICHT abgeschlossen – läuft, bis abgeschlossen wahr wird. Wer „BIS abgeschlossen" schreibt, meint dasselbe, schreibt es aber falsch. Tipp: Boolesche Logik wirklich verstehen.10) Warum strukturierte Programmierung?
Vor den 1960er Jahren war es üblich, mit GOTO-Anweisungen direkt zu beliebigen Stellen im Code zu springen. Das führte zu „Spaghetti-Code" – unverständlichen, fehleranfälligen Programmen. 1968 schrieb Edsger Dijkstra den berühmten Brief „GOTO Considered Harmful" und löste damit eine Revolution aus. Strukturierte Programmierung mit den drei Bausteinen ist seitdem Standard.
Die Vorteile der strukturierten Programmierung:
- Lesbarkeit: der Programmablauf folgt der Textreihenfolge, nicht wilden Sprüngen.
- Wartbarkeit: jeder Block hat einen klar definierten Eingang und Ausgang. Änderungen sind lokal.
- Beweisbarkeit: Korrektheit von Programmen lässt sich formal nachweisen, wenn sie strukturiert sind.
- Fehlerreduktion: viele Bug-Klassen sind in strukturiertem Code gar nicht möglich.
Heute kennen die meisten Programmiersprachen das Wort GOTO gar nicht mehr (Ausnahme: einige Maschinen-nahe Sprachen). Stattdessen gibt es Funktionen, Methoden, Klassen – höhere Abstraktionen, die ebenfalls auf den drei Grundstrukturen aufbauen.
Zusammenfassung
Kontrollstrukturen steuern den Ablauf eines Programms. Drei genügen für alle Algorithmen (Strukturtheorem von Böhm-Jacopini): Sequenz (lineare Abfolge), Auswahl/Selektion (if/else, switch/case), Schleife/Iteration (while, do-while, for, foreach). Die Bedingungen sind Boolesche Ausdrücke. Schleifenarten: while (kopfgesteuert, evtl. 0 Durchläufe), do-while (fußgesteuert, mind. 1 Durchlauf), for (Zählschleife, Anzahl bekannt), foreach (über Sammlungen iterieren). Wahl: for bei bekannter Anzahl, foreach bei Sammlungen, while bei bedingungs-abhängiger Anzahl, do-while wenn mindestens 1 Durchlauf garantiert sein muss. Verschachtelung ist die Macht: alle Bausteine beliebig kombinierbar. Zusatz-Anweisungen: break (Schleife abbrechen), continue (Iteration überspringen) – sparsam einsetzen. Klassische Stolperfallen: Endlosschleife, Off-by-one, Vergleich vs. Zuweisung, Dangling Else, fehlende Initialisierung, verdrehte Boolesche Bedingung. Historischer Kontext: vor 1968 GOTO-Spaghetti, danach strukturierte Programmierung als Standard. In allen modernen Programmiersprachen (Java, Python, C++) finden sich alle drei Bausteine wieder. Mit diesen Grundlagen kannst du jeden Algorithmus in Pseudocode oder Struktogramm ausdrücken. Nächste Lektion: Rekursion – eine spezielle Form der Wiederholung, in der eine Funktion sich selbst aufruft.
