E3 – Grundlagen der Programmierung
Programmieren als Werkzeug für Modellierung und ProblemlösenDas Themenfeld E3 Grundlagen der Programmierung ist ein zentrales Arbeitsfeld der Einführungsphase. Im Mittelpunkt steht nicht nur das Erlernen einzelner Java-Befehle, sondern der systematische Weg von der Problemstellung zur nachvollziehbaren Lösung.
Die Programmiersprache wird dabei als Mittel zum Zweck genutzt: Sie hilft, Modelle zu präzisieren, Algorithmen umzusetzen und Ergebnisse zu prüfen. Spätere Themenfelder und Projekte bauen auf diesen Grundlagen auf.
Die Kapitel folgen daher einer durchgehenden Lernlinie: Werte und Typen verstehen → Abläufe steuern → Teilaufgaben mit Methoden strukturieren → Daten in Arrays und Strings organisieren → Such- und Sortieralgorithmen entwickeln.
Kerncurriculum kompakt
Einordnung und Inhalte des Themenfelds E.3
Einordnung und Inhalte des Themenfelds E.3
A) Allgemeine Einordnung
Programmierung gehört in der Einführungsphase zu den zentralen Primärerfahrungen der Informatik. Lernende entwickeln dabei vor allem Modellierungs- und Problemlösekompetenz, indem sie schrittweise von einer Idee zu einer überprüfbaren Umsetzung gelangen.
Java wird als objektorientierte Sprache genutzt, in E3 steht jedoch zunächst die prozedurale Grundarbeit mit Datentypen, Ausdrücken, Kontrollstrukturen und Methoden im Vordergrund.
B) Inhalte des Themenfelds E.3
- Grundaufbau von Programmen, Syntax und elementare Anweisungen → Kapitel 1
- EVA-Prinzip als erstes Strukturmodell für Programme → Kapitel 1a
- Variablen, Zuweisungen, primitive Datentypen und Typkonversion → Kapitel 2
- Operatoren, Vergleiche und boolesche Bedingungen → Kapitel 3
- Kontrollstrukturen und Struktogramm-Notation als Brücke zur Algorithmik → Kapitel 4
- Methoden, Strukturierung und erste Modellierungsansätze → Kapitel 5
- Datenstrukturen mit Arrays und Strings als Grundlage algorithmischer Verarbeitung → Kapitel 6
- Einstieg in GUI und ereignisgesteuerte Anwendungen als Transferfall → Kapitel 7
- Algorithmen: Begriffe, Eigenschaften und Darstellungen als Grundlage für Verfahren → Kapitel 8
- Suchalgorithmen von linearer Suche bis Hashing mit Effizienzbezug → Kapitel 9
- Sortieralgorithmen (Selection, Insertion, Bubble) mit Vergleich der Verfahren → Kapitel 10
C) Bedeutung für diese Kursseite
Diese Seite ist bewusst als ausbaubares Gerüst angelegt. Die Kapitel bilden eine sachlogische Lernfolge: vom Aufbau einfacher Programme über Datentypen und Ausdrücke bis zu Kontrollstrukturen, Methoden und ersten grafischen Anwendungen.
Inhalte, Beispiele und Aufgaben werden in den Unterkapiteln schrittweise ergänzt.
Quelle
Hessisches Ministerium für Kultus, Bildung und Chancen (2024): Kerncurriculum gymnasiale Oberstufe Informatik, Themenfeld E.3. Fachliche Strukturorientierung ergänzt durch das begleitende Java-Skript.
Einführung in Java und Aufbau einfacher Programme
Wie Programme geschrieben, übersetzt und als Folge von Anweisungen aufgebaut werden
Wie Programme geschrieben, übersetzt und als Folge von Anweisungen aufgebaut werden
Übergang: Wir starten mit der kleinsten lauffähigen Programmeinheit. Damit wird die Grundlage gelegt, auf der im nächsten Schritt Variablen, Datentypen und Berechnungen sinnvoll aufgebaut werden.
1. Konzeptklärung: Programm, Quelltext und Ausführung
Ein Programm ist eine formal beschriebene Folge ausführbarer Anweisungen zur Lösung eines Problems.
In Java wird diese Beschreibung als Quelltext in .java-Dateien notiert.
Der Quelltext ist menschenlesbar, aber nicht direkt maschinenausführbar.
Der Quelltext ist die von Menschen formulierte, syntaktisch geregelte Beschreibung eines Programms.
2. Strukturelle Einordnung: Übersetzung und Laufzeit
Java-Programme durchlaufen zwei klar getrennte Schritte.
Zunächst übersetzt der Compiler den Quelltext in Bytecode (.class), anschließend führt die Java Virtual Machine (JVM) diesen Bytecode aus.
Die Trennung von Übersetzung und Ausführung macht nachvollziehbar, warum Übersetzungsfehler und Laufzeitfehler unterschiedliche Ursachen haben.
Ein Compiler überprüft die Syntax des Quelltexts und erzeugt aus korrektem Java-Code Bytecode.
Bytecode ist die plattformunabhängige Zwischenform eines Java-Programms, die von der JVM ausgeführt wird.
3. Formale Umsetzung: Klasse, main-Methode und Anweisung
Eine ausführbare Java-Anwendung besitzt mindestens eine Klasse mit einer main-Methode als Startpunkt.
Die Anweisungen innerhalb von main werden in der notierten Reihenfolge ausgeführt.
Eine Klasse ist ein Bauplan, der Daten und Operationen in einer gemeinsamen Struktur zusammenfasst.
Die main-Methode ist der definierte Einstiegspunkt einer Java-Anwendung (public static void main(String[] args)).
Eine Anweisung ist ein einzelner ausführbarer Programmschritt; einfache Anweisungen enden in Java mit einem Semikolon.
4. Beispiel: Minimales, vollständiges Java-Programm
public class HalloWelt {
public static void main(String[] args) {
System.out.println("Hallo Welt");
}
}
Das Beispiel enthält genau eine Klasse, genau eine Startmethode und genau eine auszuführende Anweisung. Damit ist die grundlegende Programmstruktur vollständig sichtbar, ohne zusätzliche Sprachelemente vorwegzunehmen.
5. Typische Fehlvorstellungen
Häufig wird angenommen, die Datei werde „Zeile für Zeile“ ohne Struktur ausgeführt.
Tatsächlich startet die Ausführung an der main-Methode, nicht am Anfang der Datei.
Ebenfalls verbreitet ist die Gleichsetzung von Quelltext und lauffähigem Programm. Der Quelltext muss zuerst erfolgreich übersetzt werden; erst der erzeugte Bytecode ist ausführbar.
Nachschärfung
Die Darstellung trennt nun ausdrücklich zwischen Konzept (Programm als Anweisungsfolge), formaler Syntax (Klasse und main-Signatur)
und technischem Prozess (Compiler/JVM), um typische Vermischungen dieser Ebenen zu vermeiden.
Nächster Schritt: Auf dieser Struktur werden nun Werte eingeführt: Variablen und Datentypen machen Programmzustände explizit und berechenbar.
EVA-Prinzip als Grundmodell für Programme
Programmabläufe fachlich strukturieren: Eingabe, Verarbeitung, Ausgabe
Programmabläufe fachlich strukturieren: Eingabe, Verarbeitung, Ausgabe
Bevor einzelne Sprachelemente wie Variablen, Datentypen oder Kontrollstrukturen im Detail betrachtet werden, hilft ein fachliches Strukturmodell für den gesamten Ablauf eines Programms: das EVA-Prinzip.
1. Grundidee: Drei funktionale Perspektiven auf Programmlogik
- Eingabe: Daten gelangen ins Programm.
- Verarbeitung: Daten werden geprüft, verändert, berechnet oder interpretiert.
- Ausgabe: Ergebnisse werden sichtbar gemacht oder weitergegeben.
Gute Programme trennen möglichst klar zwischen Eingabe, Verarbeitung und Ausgabe.
Das EVA-Prinzip ist damit ein hilfreiches erstes Strukturmodell, aber noch kein vollständiges Modell moderner Softwareentwicklung. Aspekte wie Objektstruktur, Zustandsverwaltung, Nebenläufigkeit oder komplexe Ereignisverarbeitung kommen später ergänzend hinzu.
Für den Einstieg sind Konsolenprogramme besonders geeignet, weil die EVA-Teile dort klar sichtbar sind; dieselben Grundideen kehren später auch in GUI- und ereignisgesteuerten Programmen wieder.
Sequenzdiagramm: EVA als GUI-Ereignisfolge
Auch bei grafischen Oberflächen bleibt die EVA-Logik erhalten: Ein Ereignis löst Verarbeitung aus, die anschließend in einer sichtbaren Ausgabe endet.
2. Beispiel: Namen einlesen und begrüßen
name = input("Wie heißt du? ")
gruss = f"Hallo, {name}!"
print(gruss)
- Eingabe:
input(...)liest den Namen ein. - Verarbeitung: Der Begrüßungstext wird zusammengesetzt.
- Ausgabe:
print(...)gibt den Text aus.
3. Beispiel: Zwei Zahlen einlesen und addieren
a = float(input("Erste Zahl: "))
b = float(input("Zweite Zahl: "))
summe = a + b
print("Summe:", summe)
- Eingabe: Zwei Zahlen werden eingelesen.
- Verarbeitung: Die Berechnung
a + bwird durchgeführt. - Ausgabe: Die berechnete Summe wird angezeigt.
4. Beispiel: Alter abfragen und mit if auswerten
alter = int(input("Wie alt bist du? "))
if alter >= 18:
meldung = "Du bist volljährig."
else:
meldung = "Du bist minderjährig."
print(meldung)
- Eingabe: Das Alter wird eingelesen.
- Verarbeitung: Eine
if-Kontrollstruktur bewertet das Alter. - Ausgabe: Die passende Meldung wird ausgegeben.
5. Beispiel: Punktzahl mit Funktion bewerten
def bewerte_punktzahl(punkte):
if punkte >= 90:
return "sehr gut"
if punkte >= 75:
return "gut"
return "ausreichend"
punkte = int(input("Punktzahl: "))
urteil = bewerte_punktzahl(punkte)
print("Bewertung:", urteil)
- Eingabe: Die Punktzahl wird eingelesen.
- Verarbeitung: Eine Funktion ordnet die Punktzahl einer Kategorie zu.
- Ausgabe: Die Bewertung wird ausgegeben.
Variablen, Zuweisungen und Datentypen
Werte speichern, verändern und passend typisieren
Werte speichern, verändern und passend typisieren
Übergang: Nach Programmgrundstruktur (Kapitel 1) und erstem Ablaufmodell über das EVA-Prinzip (Kapitel 1a) geht es jetzt um den Inhalt der Anweisungen: Werte speichern, verändern und mit passenden Typen absichern.
1. Konzeptklärung: Variable als benannter Speicherort
Eine Variable bezeichnet einen Speicherbereich, dem ein Name zugeordnet ist. Der Name ermöglicht den Zugriff auf den aktuell gespeicherten Wert im Programmablauf.
Eine Variable ist ein benannter Speicherort mit festgelegtem Datentyp und veränderlichem Wert.
2. Strukturelle Einordnung: Zustand im Programm
Variablen machen Programmzustände explizit. Während ein Programm ausgeführt wird, werden Werte gelesen, berechnet und erneut gespeichert. Dadurch lassen sich Zwischenergebnisse nachvollziehbar darstellen und weiterverarbeiten.
3. Formale Umsetzung: Deklaration, Initialisierung und Zuweisung
Die Deklaration legt Datentyp und Namen fest. Eine Initialisierung weist beim Anlegen bereits einen Startwert zu. Eine spätere Zuweisung ersetzt den bisherigen Wert der Variablen.
Eine Zuweisung ordnet einer Variablen mit dem Operator = einen neuen Wert zu und verändert damit den Programmzustand.
Ein Datentyp legt den zulässigen Wertebereich und die erlaubten Operationen für eine Variable fest.
public class VariablenDemo {
public static void main(String[] args) {
int kontoStand = 100; // Deklaration + Initialisierung
kontoStand = kontoStand + 25; // Zuweisung: Zustand ändert sich
double temperatur = 21.5;
boolean istVoll = false;
char note = 'A';
System.out.println(kontoStand);
}
}
4. Datentypen in Java: Übersicht der primitiven Typen
Die folgenden acht primitiven Datentypen sind fest in Java definiert. Sie speichern einfache Werte direkt und besitzen feste Größen und Wertebereiche.
| Datentyp | Größe | Wertebereich | Standardwert |
|---|---|---|---|
boolean | JVM-abhängig (logisch 1 Bit) | true, false | false |
char | 16 Bit | U+0000 bis U+FFFF | '\u0000' |
byte | 8 Bit | -128 bis 127 | 0 |
short | 16 Bit | -32.768 bis 32.767 | 0 |
int | 32 Bit | -2.147.483.648 bis 2.147.483.647 | 0 |
long | 64 Bit | -9.223.372.036.854.775.808 bis 9.223.372.036.854.775.807 | 0L |
float | 32 Bit | ca. ±1,4E-45 bis ±3,4E+38 | 0.0f |
double | 64 Bit | ca. ±4,9E-324 bis ±1,7E+308 | 0.0d |
5. Primitive Datentypen und Objekte sauber unterscheiden
Primitive Typen speichern unmittelbare Einzelwerte (z. B. Zahl, Zeichen, Wahrheitswert). Bei Referenztypen verweist eine Variable dagegen auf ein Objekt, das intern mehrere Daten und ggf. Methodenbezug zusammenfasst.
int punkte = 42; // primitiver Wert liegt direkt vor
int[] messwerte = {3, 5, 8}; // Variable speichert Referenz auf ein Array-Objekt
String name = "Lea"; // Referenz auf ein String-Objekt
Diese Unterscheidung ist für spätere Kapitel zentral: Arrays und andere Datenstrukturen arbeiten mit Referenzen auf Objekte, während numerische Berechnungen häufig auf primitiven Typen stattfinden.
6. Typumwandlung
Bei der Typumwandlung wird ein Wert in einen anderen Datentyp überführt. Java unterscheidet automatische (implizite) Umwandlung und explizites Casting.
Automatische (implizite) Umwandlung
int anzahl = 7;
double alsDouble = anzahl; // int -> double
float alsFloat = anzahl; // int -> float
Arithmetische Beförderung bei kleinen Ganzzahltypen
byte a = 10;
short b = 20;
int summe = a + b; // byte/short werden in Ausdrücken zu int
Explizite Umwandlung (Casting)
double preis = 19.99;
int euro = (int) preis; // 19, Nachkommastellen fallen weg
long gross = 4_000_000_000L;
int klein = (int) gross; // Überlauf möglich
float note = 2.7f;
int ganzzahl = (int) note; // 2
7. Typische Fehlvorstellungen
Der Operator = wird oft als mathematische Gleichheit interpretiert.
In Java bedeutet er Zuweisung: Der rechte Ausdruck wird ausgewertet und sein Ergebnis links gespeichert.
Ebenso verbreitet ist die Annahme, der Datentyp sei nur „Beschriftung“. Tatsächlich bestimmt der Typ, welche Werte zulässig sind, wie sie gespeichert werden und ob eine Umwandlung automatisch oder nur per Casting möglich ist.
Nachschärfung
Die Kapitelstruktur verbindet jetzt Variablenarbeit, Typsystem und Typumwandlung systematisch. Damit ist eine tragfähige Basis gelegt, um in späteren Kapiteln Datenstrukturen, Arrays und algorithmische Verarbeitung über primitive Werte und Referenzen konsistent zu behandeln.
Nächster Schritt: Mit diesen Werten lassen sich nun Ausdrücke und Bedingungen formulieren, die anschließend die Ablaufsteuerung über Kontrollstrukturen ermöglichen.
Operatoren und logische Ausdrücke
Rechnen, vergleichen und Bedingungen formulieren
Rechnen, vergleichen und Bedingungen formulieren
Übergang: Variablen und Datentypen liefern die Wertebasis. Jetzt wird geklärt, wie diese Werte über Operatoren zu Berechnungen, Vergleichen und Bedingungen verknüpft werden.
1. Konzeptklärung: Ausdruck als auswertbare Struktur
Ein Ausdruck kombiniert Werte, Variablen, Konstanten und Operatoren zu einer auswertbaren Einheit. Das Ergebnis eines Ausdrucks hat einen Datentyp, zum Beispiel numerisch oder boolesch. Operatoren sind damit nicht nur Rechenzeichen, sondern zentrale Bausteine zur Formulierung von Berechnungen und Bedingungen.
Ein Ausdruck ist eine Kombination aus Operanden und Operatoren, die zu einem Wert ausgewertet wird.
Ein Operator legt fest, wie mit Operanden gerechnet, verglichen oder logisch verknüpft wird.
2. Strukturelle Einordnung: Ausdrücke im Programmablauf
Arithmetische Ausdrücke erzeugen numerische Ergebnisse, Vergleichsausdrücke erzeugen Wahrheitswerte, und logische Ausdrücke verknüpfen Wahrheitswerte zu komplexeren Bedingungen. Damit bilden sie die fachliche Brücke zwischen Datenverarbeitung und Ablaufsteuerung.
3. Formale Umsetzung: Operatorgruppen, Priorität und Klammerung
Typische arithmetische Operatoren sind +, -, *, / und %.
Vergleichsoperatoren sind unter anderem ==, !=, <, <=, >, >=.
Logische Operatoren wie &&, || und ! arbeiten auf booleschen Werten.
Klammern steuern die Auswertungsreihenfolge explizit und reduzieren Mehrdeutigkeiten.
public class OperatorenDemo {
public static void main(String[] args) {
int a = 8;
int b = 3;
int summe = a + b * 2; // arithmetischer Ausdruck
boolean istGleich = (a == b); // Vergleichsausdruck
boolean istGueltig = (a > b) && (b > 0); // logischer Ausdruck
System.out.println(summe);
System.out.println(istGleich);
System.out.println(istGueltig);
}
}
4. Beispielanalyse: numerisches vs. boolesches Ergebnis
a + b * 2 liefert einen numerischen Wert.
a == b liefert den Wahrheitswert true oder false.
(a > b) && (b > 0) verknüpft zwei boolesche Teilausdrücke zu einer Gesamtbedingung,
die später in if- oder while-Strukturen verwendet werden kann.
5. Logische Operatoren in Bedingungen
Sobald Bedingungen aus mehreren Teilaussagen bestehen, werden logische Operatoren zur Verknüpfung benötigt.
Sie entscheiden, ob eine Gesamtbedingung in Kontrollstrukturen wie if, while oder for
als true oder false ausgewertet wird.
| Name | Java-Notation | Java-Beispiel |
|---|---|---|
| Logical and | && | (sum > min) && (sum < max) |
| Logical or | || | (answer == 'y') || (answer == 'Y') |
| Logical not | ! | !(number < 0) |
Die Tabelle zeigt die typische Rollenverteilung: && fordert, dass beide Teilbedingungen gelten,
|| akzeptiert mindestens eine zutreffende Bedingung, und ! negiert einen vorhandenen Wahrheitswert.
6. Wahrheitstabelle für &&, || und !
Wahrheitstabellen helfen dabei, das Verhalten logischer Operatoren exakt zu überprüfen. Gerade bei verschachtelten Bedingungen in Schleifen und Verzweigungen lässt sich so vorab prüfen, welche Kombinationen zu einer Ausführung des jeweiligen Blocks führen.
| A | B | A && B | A || B | !(A) |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
Für die Praxis heißt das: Bedingungen lassen sich aus mehreren Teilaussagen zusammensetzen,
um Programmabläufe präzise zu steuern. Das ist zentral für Grenzprüfungen in if-Anweisungen,
Abbruchkriterien in while-Schleifen und kombinierte Laufbedingungen in for-Schleifen.
7. Typische Fehlvorstellungen
Ein häufiger Fehler ist die Verwechslung von = (Zuweisung) und == (Vergleich).
Dadurch wird statt einer Bedingung unbeabsichtigt ein Wert zugewiesen oder ein Syntaxfehler erzeugt.
Ebenso wird oft angenommen, jeder Ausdruck liefere eine Zahl. Vergleichs- und logische Ausdrücke liefern jedoch boolesche Werte und sind damit direkt als Bedingungen interpretierbar.
Ohne Klammerung wird die Priorität von Operatoren häufig falsch eingeschätzt. Explizite Klammern sichern die beabsichtigte Auswertungsreihenfolge.
Nachschärfung
Die Darstellung trennt jetzt systematisch zwischen Berechnung, Vergleich und logischer Verknüpfung, damit Ausdrücke als fachliche Grundlage späterer Kontrollstrukturen klar erkennbar werden.
Nächster Schritt: Diese Bedingungen werden nun genutzt, um komplette Abläufe mit Verzweigungen und Schleifen zu steuern.
Kontrollstrukturen
Abläufe steuern und mit Struktogrammen systematisch modellieren
Abläufe steuern und mit Struktogrammen systematisch modellieren
Übergang: Nach den logischen Ausdrücken folgt der nächste Schritt der Lernlinie: Aus einzelnen Bedingungen werden jetzt vollständige, steuerbare Abläufe.
A) Einführung: Was sind Kontrollstrukturen?
Kontrollstrukturen steuern den Ablauf eines Programms. Sie legen fest, ob Anweisungen nacheinander ausgeführt werden (Sequenz), ob zwischen Alternativen entschieden wird (Verzweigung) oder ob Schritte wiederholt werden (Schleife). Damit bilden sie die Brücke von einzelnen Befehlen zur algorithmischen Modellierung.
B) Struktogramm-Notation (grundlegend)
Struktogramme beschreiben Ablauflogik in Blöcken. Die Notation ist sprachneutral und passt direkt zum eingebundenen Struktogramm-Tool: Sequenz als Folge von Blöcken, Verzweigung als geteilte Entscheidung, Schleifen als wiederholte Blöcke mit Bedingung.
Struktogramm: Grundnotation
1) Bedingte Anweisung (if / if-else)
Erklärung: Eine Bedingung steuert, welcher Pfad ausgeführt wird. Bei if-else sind zwei Pfade explizit vorhanden.
if (temperatur < 0) {
status = "Frost";
} else {
status = "kein Frost";
}
Struktogramm-Konvention: Verzweigung
Leselogik: Was passiert hier? Es wird genau ein Zweig ausgeführt. Wie liest man das Struktogramm? Erst Bedingung prüfen, dann den passenden Pfad verfolgen.
2) While-Schleife
Erklärung: Die while-Schleife ist kopfgesteuert. Die Bedingung wird vor jedem Durchlauf geprüft.
int i = 0;
while (i < 3) {
System.out.println(i);
i++;
}
Struktogramm-Konvention: kopfgesteuerte Schleife
Leselogik: Was passiert hier? Der Block läuft wiederholt, solange die Bedingung wahr bleibt. Wie liest man das Struktogramm? Bedingung oben, dann Schleifenkörper, danach Rücksprung zur Bedingung.
3) For-Schleife
Erklärung: Die for-Schleife bündelt Initialisierung, Bedingung und Schrittweite. Sie ist die typische Zählschleife und bereitet die Iteration über Arrays vor.
int[] werte = {7, 4, 9};
for (int i = 0; i < werte.length; i++) {
System.out.println(werte[i]);
}
Struktogramm-Konvention: Zählschleife
Leselogik: Was passiert hier? Jeder Index wird genau einmal besucht. Wie liest man das Struktogramm? Ein Zählbereich steuert die Wiederholung, der Körper verarbeitet pro Durchlauf ein Element.
4) Do-While-Schleife
Erklärung: Die do-while-Schleife ist fußgesteuert. Der Schleifenkörper wird mindestens einmal ausgeführt.
int versuche = 0;
do {
versuche++;
} while (versuche < 1);
Struktogramm-Konvention: fußgesteuerte Schleife
Leselogik: Was passiert hier? Ein erster Durchlauf ist garantiert, erst dann wird geprüft. Wie liest man das Struktogramm? Zuerst den Block, dann die Bedingung als Fortsetzungsentscheidung.
5) Switch-Anweisung
Erklärung: switch modelliert eine Mehrfachverzweigung und ersetzt lange Ketten verschachtelter if-Abfragen.
switch (note) {
case 1: text = "sehr gut"; break;
case 2: text = "gut"; break;
default: text = "weitere";
}
Struktogramm-Konvention: Mehrfachverzweigung
Leselogik: Was passiert hier? Genau ein passender Fall wird gewählt, sonst der Default-Pfad. Wie liest man das Struktogramm? Von der Auswahlbedingung zu genau einem der Alternativpfade.
Brücke zur Algorithmik
Schleifen liefern die Iterationslogik für Arrays, Bedingungen liefern die Entscheidungslogik für Suche und Sortierung, und Struktogramme machen beides als modellierbaren Ablauf sichtbar. Damit ist der Übergang zur Strukturierung mit Methoden vorbereitet: Kontrollstrukturen werden dort als wiederverwendbare Teilabläufe gekapselt.
Nächster Schritt: Aus gesteuerten Abläufen werden nun wiederverwendbare Bausteine – Methoden als Strukturprinzip.
Methoden, Strukturierung und erste Modellierung
Programme in sinnvoll gegliederte Bausteine zerlegen
Programme in sinnvoll gegliederte Bausteine zerlegen
Übergang: Kontrollstrukturen beschreiben den Ablauf – Methoden ordnen diesen Ablauf jetzt in wiederverwendbare Teilaufgaben.
1. Was ist eine Methode?
Eine Methode ist ein benannter, wiederverwendbarer Ablaufblock innerhalb einer Klasse. Sie wird nur ausgeführt, wenn sie über einen Methodenaufruf gestartet wird. Damit werden Programme nicht als „ein großer Block“, sondern als geordnete Teilaufgaben aufgebaut.
Eine Methode bündelt eine Teilaufgabe mit klarer Schnittstelle aus Eingaben (Parameter) und optionalem Ergebnis (Rückgabewert).
2. Warum nutzt man Methoden?
Methoden verbessern Lesbarkeit, Wartbarkeit und Wiederverwendbarkeit. Wenn dieselbe Logik mehrfach gebraucht wird, wird sie einmal definiert und anschließend an mehreren Stellen aufgerufen. So entsteht ein strukturierter Übergang von linearen Programmen zu algorithmisch geplanten Lösungen.
3. Aufbau einer Methode: Methodenkopf und Methodenrumpf
Eine Methodendeklaration besteht aus Methodenkopf und Methodenrumpf. Im Kopf stehen Sichtbarkeit, ggf. static, Rückgabetyp, Name und Parameterliste. Im Rumpf steht die eigentliche Verarbeitung.
public static int berechneRabatt(int preis, int prozent) {
int rabatt = preis * prozent / 100;
return rabatt;
}
Leselogik: public static int berechneRabatt(int preis, int prozent) ist der Kopf.
Der Block zwischen { und } ist der Rumpf.
4. Methoden aufrufen: Name + Klammern
Eine Methode wird über ihren Namen mit Klammern aufgerufen. Einmal definierte Methoden können mehrfach aufgerufen werden, auch mit unterschiedlichen Eingaben.
public static void main(String[] args) {
begruessung();
begruessung();
}
public static void begruessung() {
System.out.println("Willkommen im Kurs E3.");
}
Die Methode begruessung() besitzt keine Parameter und keinen Rückgabewert.
Sie führt beim Aufruf nur eine Aktion aus.
5. Parameter: Eingaben für eine Teilaufgabe
Parameter machen Methoden flexibel. Statt feste Werte im Methodenrumpf zu verwenden, werden die Werte beim Aufruf übergeben.
public static void ausgabeTicketpreis(int preis) {
System.out.println("Ticketpreis: " + preis + " €");
}
public static void main(String[] args) {
ausgabeTicketpreis(29);
ausgabeTicketpreis(45);
}
Die Methode bleibt gleich, nur das Argument ändert sich. So wird dieselbe Logik für verschiedene Situationen genutzt.
6. Rückgabewerte, return und void
Methoden mit Rückgabetyp liefern ein Ergebnis an die Aufrufstelle zurück.
Das Ergebnis wird über return zurückgegeben.
Bei void-Methoden steht die Aktion im Vordergrund, nicht ein berechneter Rückgabewert.
// Methode mit Rückgabewert
public static int berechneGesamtpreis(int preisProTicket, int anzahl) {
return preisProTicket * anzahl;
}
// void-Methode
public static void zeigeHinweis() {
System.out.println("Bitte Anzahl überprüfen.");
}
public static void main(String[] args) {
int gesamt = berechneGesamtpreis(40, 3);
System.out.println("Gesamtpreis: " + gesamt);
zeigeHinweis();
}
Modellierungsbezug: Berechnungen (z. B. Preise, Zeiten, Indizes) eignen sich oft für Methoden mit Rückgabewert,
während Statusmeldungen oder Ausgaben häufig als void-Methoden formuliert werden.
7. static im aktuellen E3-Kontext
In E3 werden viele Beispiele innerhalb einer Klasse mit main umgesetzt.
Damit main eine Methode direkt aufrufen kann, wird sie in diesem Kontext meist als static notiert.
Didaktisch genügt hier: static bedeutet, dass die Methode zur Klasse gehört und ohne erzeugtes Objekt nutzbar ist.
8. Methoden als Strukturierungsprinzip
Größere Programme werden in fachlich sinnvolle Teilaufgaben zerlegt: Eingaben prüfen, Werte berechnen, Ergebnisse ausgeben. Dadurch wird der Programmablauf besser lesbar und leichter wartbar. Diese Denkweise verbindet Methoden direkt mit Kontrollstrukturen, Datenstrukturen und späteren Algorithmus-Kapiteln. Auch im Struktogramm kann ein Methodenaufruf als Blockaufruf modelliert werden.
public static boolean istGueltigerIndex(int index, int[] daten) {
return index >= 0 && index < daten.length;
}
public static int leseWertSicher(int index, int[] daten) {
if (istGueltigerIndex(index, daten)) {
return daten[index];
}
return -1;
}
Hier ruft eine Methode eine andere auf.
Kontrollstruktur (if) und Datenstruktur (int[]) werden sauber in Teilaufgaben gegliedert.
9. Methodenüberladung in tragfähigem Umfang
Bei der Methodenüberladung haben Methoden denselben Namen, aber unterschiedliche Parameterlisten. Der Name beschreibt die fachliche Aufgabe, die Parameterliste die konkrete Variante.
public static int addiere(int a, int b) {
return a + b;
}
public static double addiere(double a, double b) {
return a + b;
}
Die Aufrufe addiere(3, 4) und addiere(2.5, 1.5) wählen automatisch die passende Methode.
Für E3 reicht dieses Grundverständnis; weiterführende Spezialfälle folgen später.
10. Typische Fehlvorstellungen (kompakt)
Methoden werden nicht automatisch ausgeführt, sondern nur durch Aufruf.
Parameter sind lokal und keine globalen Variablen.
Ein Rückgabewert entsteht nur bei Methoden mit passendem Rückgabetyp und return.
Methodenüberladung unterscheidet sich über die Parameterliste, nicht über den Methodennamen allein.
Nächster Schritt: Die so strukturierten Teilaufgaben arbeiten nun auf größeren Datenmengen – dafür werden Arrays und Strings als Datenstrukturen benötigt.
Datenstrukturen
Arrays und Strings als strukturierte Grundlage für algorithmisches Arbeiten
Arrays und Strings als strukturierte Grundlage für algorithmisches Arbeiten
Übergang: Nach der methodischen Strukturierung folgt die Datenperspektive: Die gleiche Problemstellung wird nun nicht mehr mit Einzelwerten, sondern mit geordneten Datensammlungen bearbeitet.
A) Einführung: Warum Datenstrukturen?
Einzelne Variablen reichen nur für einzelne Werte. Sobald mehrere zusammengehörige Informationen verarbeitet werden sollen (z. B. mehrere Messwerte oder ein ganzer Text), braucht man Datenstrukturen. Sie organisieren Daten so, dass systematische Verarbeitung mit Schleifen und Bedingungen möglich wird.
Damit entsteht die fachliche Entwicklung dieses Kapitels: von einzelnen Variablen hin zu strukturierten Datensammlungen und weiter zur algorithmischen Verarbeitung.
B) Arrays als zentrale Datenstruktur
Ein Array speichert mehrere Werte gleichen Typs unter einem Namen. Die Länge ist nach der Erzeugung fest. Auf einzelne Elemente greift man über den Index zu.
// Initialisierung mit fester Länge und Startwerten
int[] messwerte = {18, 7, 42, 13, 29, 5};
// Zugriff über Index
int erstesElement = messwerte[0];
int drittesElement = messwerte[2];
Der Nutzen von Arrays liegt nicht nur in der Speicherung, sondern vor allem im geordneten Zugriff: Positionen sind eindeutig adressierbar und können deshalb gezielt geprüft, verändert oder verglichen werden.
// Durchlaufen eines Arrays mit for-Schleife
for (int i = 0; i < messwerte.length; i++) {
System.out.println("Index " + i + " -> " + messwerte[i]);
}
Das Durchlaufen (Iterieren) über Arrays verbindet dieses Kapitel direkt mit den Kontrollstrukturen aus Kapitel 4.
C) Strings als besondere Datenstruktur für Text
Ein String steht in Java für Text und kann als Folge einzelner Zeichen verstanden werden. Wie bei Arrays spielt die Position eine Rolle: Zeichen können über ihren Index betrachtet werden.
String kurs = "Informatik";
int laenge = kurs.length();
char erstesZeichen = kurs.charAt(0);
String kuerzer = kurs.substring(0, 5); // "Infor"
Strings sind für Text optimiert und bieten dafür eigene Operationen. Gleichzeitig bleiben sie strukturiert genug, um Zeichenfolgen systematisch zu durchlaufen.
// Iteration über alle Zeichen eines Strings
for (int i = 0; i < kurs.length(); i++) {
System.out.println(kurs.charAt(i));
}
D) Gemeinsamkeiten von Arrays und Strings
- Beide speichern mehrere Werte in einer geordneten Struktur.
- Bei beiden erfolgt der Zugriff positionsbezogen über Indizes.
- Beide können mit Schleifen vollständig durchlaufen werden (Iteration).
- Beide bilden damit eine direkte Grundlage für algorithmische Verfahren.
Diese gemeinsame Strukturperspektive ist entscheidend: Lernende betrachten Arrays und Strings nicht als isolierte Einzelthemen, sondern als Varianten derselben Grundidee „strukturierte Daten“.
E) Einordnung: primitive Datentypen, komplexe Strukturen und Ausblick
Im Unterschied zu primitiven Datentypen wie int oder boolean,
die jeweils einen einzelnen Wert speichern, repräsentieren Arrays und Strings
mehrere, strukturierte Werte in einer gemeinsamen Form.
Für die nächsten Kapitel ist diese Einordnung zentral: Algorithmen in Kapitel 8 bis 10 arbeiten auf genau solchen Strukturen, etwa beim Suchen und Sortieren in Arrays. Zugleich ist der Blick nach vorne wichtig: Strings sind in Java Objekte, und komplexere Datenorganisation wird in der Qualifikationsphase systematisch über Objektstrukturen vertieft (siehe Q2.1).
Nächster Schritt: Damit ist die Datenbasis komplett – jetzt werden allgemeine Algorithmen formuliert, die auf diesen Strukturen arbeiten.
Grafische Benutzeroberflächen und ereignisgesteuerte Programmierung
Interaktion über Fenster, Eingaben und Aktionen
Interaktion über Fenster, Eingaben und Aktionen
Übergang: Nach dem EVA-Einstieg mit Konsolenprogrammen folgt nun der Transfer: Grafische Benutzeroberflächen setzen dieselbe Grundidee um, aber unter Ereignissteuerung.
GUI = EVA unter Ereignissteuerung.
1. EVA in grafischen Benutzeroberflächen
Bei einer GUI arbeitet das Programm nicht mehr nur in einer festen linearen Reihenfolge. Stattdessen wartet es auf Ereignisse (z. B. Klicks) und führt dann gezielt Verarbeitungsschritte aus.
- Eingabe: Textfelder und Benutzeraktionen liefern Daten oder lösen Ereignisse aus.
- Verarbeitung: Funktionen beziehungsweise Event-Handler prüfen, berechnen oder interpretieren diese Daten.
- Ausgabe: Labels, Meldungen und Anzeigen machen Ergebnisse sichtbar.
Wichtig: Ein ist keine direkte Dateneingabe. Er ist ein Auslöser, der ein Ereignis erzeugt und damit die Verarbeitung startet.
2. Beispiel: Begrüßung mit Texteingabe
import tkinter as tk
def begruessen():
name = eingabe_name.get().strip()
if not name:
name = "Gast"
label_ausgabe.config(text=f"Hallo, {name}!")
fenster = tk.Tk()
fenster.title("Begrüßung")
eingabe_name = tk.Entry(fenster, width=20)
eingabe_name.pack(pady=4)
button = tk.Button(fenster, text="Begrüßen", command=begruessen)
button.pack(pady=4)
label_ausgabe = tk.Label(fenster, text="Bitte Namen eingeben.")
label_ausgabe.pack(pady=4)
fenster.mainloop()
- Eingabe: Name im Textfeld, Klick auf den Button.
- Verarbeitung: Event-Handler
begruessen()liest und prüft die Eingabe. - Ausgabe: Das Label zeigt die Begrüßung an.
3. Beispiel: Addition zweier Zahlen
import tkinter as tk
def addiere():
a = float(eingabe_a.get())
b = float(eingabe_b.get())
ergebnis = a + b
label_summe.config(text=f"Summe: {ergebnis}")
fenster = tk.Tk()
fenster.title("Addition")
eingabe_a = tk.Entry(fenster, width=12)
eingabe_b = tk.Entry(fenster, width=12)
eingabe_a.pack(pady=2)
eingabe_b.pack(pady=2)
button = tk.Button(fenster, text="Addieren", command=addiere)
button.pack(pady=4)
label_summe = tk.Label(fenster, text="Noch kein Ergebnis.")
label_summe.pack(pady=4)
fenster.mainloop()
- Eingabe: Zwei Zahlen im GUI und Klick auf „Addieren“.
- Verarbeitung: Event-Handler
addiere()konvertiert und berechnet. - Ausgabe: Das Label zeigt die Summe.
4. Beispiel: Alter prüfen mit Entscheidung
import tkinter as tk
def pruefe_alter():
alter = int(eingabe_alter.get())
if alter >= 18:
text = "volljährig"
else:
text = "minderjährig"
label_status.config(text=f"Status: {text}")
fenster = tk.Tk()
fenster.title("Altersprüfung")
eingabe_alter = tk.Entry(fenster, width=10)
eingabe_alter.pack(pady=4)
button = tk.Button(fenster, text="Prüfen", command=pruefe_alter)
button.pack(pady=4)
label_status = tk.Label(fenster, text="Bitte Alter eingeben.")
label_status.pack(pady=4)
fenster.mainloop()
- Eingabe: Alter im Textfeld und Klick auf „Prüfen“.
- Verarbeitung: Event-Handler mit
if-Entscheidung. - Ausgabe: Das Label zeigt den Status an.
5. Was passiert beim Klick auf einen Button?
Beim Start der Anwendung werden GUI-Elemente erzeugt und ein Event-Handler mit dem Button verknüpft.
Nach der Initialisierung wartet die Ereignisschleife (mainloop()) auf Aktionen.
Erst beim Klick wird der verknüpfte Handler ausgeführt, verarbeitet die aktuellen Eingaben und aktualisiert die Ausgabe.
Damit bleibt die Leitidee aus dem EVA-Abschnitt erhalten: Eingabe und Ausgabe sind sichtbar in der Oberfläche, während die Verarbeitung in klar abgegrenzten Funktionen stattfindet.
Nächster Schritt: Im folgenden Kapitel werden diese Bausteine als allgemeine Algorithmen abstrahiert.
Algorithmen
Problemlösungen als endliche Schrittfolgen modellieren und darstellen
Problemlösungen als endliche Schrittfolgen modellieren und darstellen
A) Was ist ein Algorithmus?
Nach Variablen, Kontrollstrukturen, Methoden und Datenstrukturen folgt nun die übergeordnete Perspektive: Ein Algorithmus beschreibt, wie diese Bausteine gezielt zu einer Lösung zusammenspielen.
Ein Algorithmus ist eine zielgerichtete, endliche Schrittfolge zur Lösung eines Problems. Er beschreibt nicht nur ein Ergebnis, sondern den reproduzierbaren Weg dorthin.
Positionierung: Dieses Kapitel behandelt den allgemeinen Begriff Algorithmus; die nächsten Kapitel zeigen konkrete Klassen davon: Suchalgorithmen und Sortieralgorithmen.
B) Eigenschaften von Algorithmen
- Endlichkeit: Ein Algorithmus endet nach einer begrenzten Zahl von Schritten.
- Eindeutigkeit: Jeder Schritt ist klar festgelegt; es gibt keine unklaren Anweisungen.
- Ausführbarkeit: Alle Schritte sind mit den verfügbaren Operationen tatsächlich durchführbar.
- Allgemeinheit: Der Ablauf gilt für eine Klasse ähnlicher Eingaben, nicht nur für einen Einzelfall.
C) Darstellung von Algorithmen
Algorithmen können als Text, als Code oder als Struktogramm beschrieben werden. Text erklärt die Idee, Code macht sie ausführbar, Struktogramme machen die Ablaufstruktur sichtbar und schließen direkt an Kapitel 4 (Kontrollstrukturen) an.
D) Beispielalgorithmus: Minimum in einem Array bestimmen
Kurzbeschreibung: Das Array wird linear durchlaufen. Wird ein kleinerer Wert gefunden, ersetzt er das aktuelle Minimum.
int minimum(int[] werte) {
int min = werte[0];
for (int i = 1; i < werte.length; i++) {
if (werte[i] < min) {
min = werte[i];
}
}
return min;
}
Struktogramm: Minimumsuche (linear)
Leselogik: Initialisiere ein Startminimum, durchlaufe alle weiteren Werte, aktualisiere bei kleinerem Fund und gib am Ende das Minimum zurück.
E) Bedeutung für die Informatik
Algorithmen verbinden Kontrollstrukturen (Ablaufsteuerung) mit Datenstrukturen (Datenbasis). Auf diesem Fundament bauen die nächsten Kapitel auf: erst Suchalgorithmen, dann Sortieralgorithmen und deren Effizienzvergleich.
Nächster Schritt: Zuerst wird gesucht (finden), danach sortiert (ordnen) – beide Verfahren arbeiten auf derselben Datenbasis.
Übergang: Nach dem allgemeinen Algorithmusbegriff folgt jetzt die erste konkrete Anwendungsklasse: Suchalgorithmen.
1. Konzeptklärung: Suchen in strukturierten Daten
Suchen bedeutet: Prüfen, ob ein Suchschlüssel in einer Datenstruktur vorkommt und wo er liegt. Die Wahl des Suchalgorithmus hängt direkt von der Struktur der Daten ab.
2. Lineare Suche
Die lineare Suche durchläuft ein Array von vorne nach hinten. In jedem Schritt wird genau ein Element mit dem Suchschlüssel verglichen. Abbruch: bei Treffer oder am Ende des Arrays.
Array: [18, 7, 42, 13, 29, 5], Suche: 13
Schritt 1: 18 != 13
Schritt 2: 7 != 13
Schritt 3: 42 != 13
Schritt 4: 13 == 13 → Treffer
Was passiert hier? Der Suchbereich bleibt immer das ganze Restarray. Die Strategie ist einfach, funktioniert immer, braucht aber im ungünstigen Fall viele Vergleiche.
boolean linearSuche(int[] a, int schluessel) {
int i = 0;
while (i < a.length && a[i] != schluessel) {
i++;
}
return i < a.length;
}
Struktogramm: Lineare Suche
Was zeigt dieses Struktogramm? Die Suche ist als Wiederholung mit integrierter Auswahl modelliert: prüfen, ggf. abbrechen, sonst weiterlaufen.
3. Binäre Suche
Die binäre Suche funktioniert nur bei sortierten Daten. Sie prüft die Mitte und halbiert danach den Suchbereich (links oder rechts). Das ist das Prinzip „Teile und herrsche“.
Sortiertes Array: [5, 7, 13, 18, 29, 42], Suche: 29
links=0, rechts=5, mitte=2 → 13 zu klein → rechten Teil nehmen
links=3, rechts=5, mitte=4 → 29 gefunden
Was passiert hier? Der Suchbereich wird in jedem Schritt kleiner. Dadurch sinkt die Zahl der Vergleiche deutlich gegenüber der linearen Suche.
boolean binaereSuche(int[] a, int schluessel) {
int links = 0, rechts = a.length - 1;
while (links <= rechts) {
int mitte = (links + rechts) / 2;
if (a[mitte] == schluessel) return true;
if (a[mitte] < schluessel) links = mitte + 1;
else rechts = mitte - 1;
}
return false;
}
Struktogramm: Binäre Suche
Was zeigt dieses Struktogramm? Die Entscheidungsstruktur halbiert den Suchraum systematisch: Treffer, rechts weitersuchen oder links weitersuchen.
4. Hashing
Hashing berechnet aus dem Suchschlüssel direkt eine Position in einer Hashtabelle, statt Schritt für Schritt zu vergleichen.
Hashfunktion: h(k) = k mod 13
k = 1849 → h(1849) = 3
k = 1862 → h(1862) = 3 (Kollision)
Was passiert hier? Zwei Schlüssel können auf denselben Index fallen (Kollision). Dann braucht man eine Kollisionsstrategie, z. B. lineares Verschieben zur nächsten freien Position im Array.
Struktogramm: Hashing (vereinfacht)
Was zeigt dieses Struktogramm? Hashing ersetzt viele Vergleiche durch eine direkte Indexberechnung und eine kurze Fallunterscheidung.
Hashing ordnet Schlüssel per Berechnungsfunktion einem Index zu; eine Kollision liegt vor, wenn zwei Schlüssel denselben Index erzeugen.
5. Effizienzvergleich beim Suchen
Nicht Zahlen auswendig lernen, sondern Zusammenhänge verstehen: Struktur und Vorarbeit bestimmen die Suchgeschwindigkeit.
- Lineare Suche: robust, aber viele Vergleiche bei großen Datenmengen.
- Binäre Suche: deutlich weniger Vergleiche, benötigt vorher sortierte Daten.
- Hashing: sehr schnelle Zugriffe, benötigt Hashfunktion und Umgang mit Kollisionen.
Nächster Schritt: Für die binäre Suche ist Sortierung eine zentrale Voraussetzung – daher folgt jetzt die zweite Anwendungsklasse: Sortieralgorithmen.
Übergang: Nach dem Finden folgt das Ordnen: Sortieralgorithmen strukturieren dieselben Daten, damit nachgelagerte Verarbeitung effizienter wird.
1. Konzeptklärung: Ordnung als algorithmisches Ziel
Sortieren erzeugt Ordnung. Diese Ordnung ist oft Voraussetzung für effiziente Suche, insbesondere für die binäre Suche. Leitidee: Erst sortieren, dann schneller suchen.
2. Selection Sort
In jedem Durchlauf wird das kleinste Element im unsortierten Teil gesucht und an den Anfang dieses Teilbereichs getauscht.
[18, 7, 42, 13, 29, 5]
1. kleinstes=5 → Tausch mit Position 0 → [5, 7, 42, 13, 29, 18]
2. kleinstes=7 → bleibt vorne → [5, 7, 42, 13, 29, 18]
3. kleinstes=13 → Tausch mit Position 2 → [5, 7, 13, 42, 29, 18]
Was passiert hier? Links wächst der sortierte Teil, rechts schrumpft der unsortierte Teil.
Struktogramm: Selection Sort
Was zeigt dieses Struktogramm? Eine äußere Schleife fixiert die Grenze des sortierten Bereichs, die innere Schleife sucht jeweils das Minimum.
3. Insertion Sort
Insertion Sort nimmt nacheinander ein Element aus dem unsortierten Teil und fügt es an der passenden Stelle in den sortierten Teil ein – wie beim Sortieren von Spielkarten.
[18 | 7, 42, 13, 29, 5]
7 einsortieren → [7, 18 | 42, 13, 29, 5]
42 einsortieren → [7, 18, 42 | 13, 29, 5]
13 einsortieren → [7, 13, 18, 42 | 29, 5]
Was passiert hier? Der sortierte Bereich wird schrittweise aufgebaut; Einfügen kann Verschiebungen verursachen.
Struktogramm: Insertion Sort
Was zeigt dieses Struktogramm? Das neue Element wird aufgenommen, nach links eingeordnet und der sortierte Bereich dadurch erweitert.
4. Bubble Sort
Bubble Sort vergleicht benachbarte Elemente und vertauscht sie bei falscher Reihenfolge. Dadurch „wandern“ große Elemente in jedem Durchlauf weiter nach hinten.
Start: [18, 7, 42, 13, 29, 5]
1. Durchlauf → [7, 18, 13, 29, 5, 42]
2. Durchlauf → [7, 13, 18, 5, 29, 42]
...
Was passiert hier? Nach jedem Durchlauf steht am rechten Rand mindestens ein Element an seiner Endposition.
Struktogramm: Bubble Sort
Was zeigt dieses Struktogramm? Zwei verschachtelte Schleifen steuern die wiederholten Nachbarvergleiche; falsche Reihenfolgen werden lokal getauscht.
5. Effizienz beim Sortieren
Verglichen werden vor allem Zahl der Vergleiche und Zahl der Vertauschungen/Verschiebungen:
- Selection Sort: wenige Tauschaktionen, aber viele Vergleiche.
- Insertion Sort: bei nahezu sortierten Daten oft günstig.
- Bubble Sort: anschaulich, aber meist höherer Tauschaufwand.
Verzahnung als Denkmodell
Die fachliche Reihenfolge ist bewusst durchgängig: Daten strukturieren → darin suchen → durch Sortierung Suche effizienter machen. So werden Datenstruktur, Algorithmus und Effizienz als zusammenhängendes Modell sichtbar.
Erreicht: Die Lernlinie von Werten bis zu Algorithmen ist geschlossen; alle Kapitelbausteine greifen nun als ein gemeinsames Denkmodell ineinander.