Felder: viele Werte unter einem Namen
Bisher hatte jede Variable genau einen Wert. Sobald eine Aufgabe von „den Messwerten“, „allen Kunden“ oder „einer Liste von Preisen“ spricht, brauchst du ein Feld (Array). Stell dir ein Feld als Reihe nummerierter Fächer vor: Jedes Fach enthält einen Wert, und die Nummer des Fachs heißt Index. Das Feld zahlen mit vier Werten sieht so aus:
| Index i | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| zahlen[i] | 4 | 9 | 2 | 7 |
Auf ein einzelnes Fach greifst du mit dem Index in eckigen Klammern zu: zahlen[2] ist 9, zahlen[4] ist 7. Der Index darf auch eine Variable sein, und genau das macht Felder so nützlich: zahlen[i] meint je nach Wert von i ein anderes Fach. Die Anzahl der Elemente heißt im Kurs n; manche Aufgaben schreiben stattdessen laenge(zahlen) oder geben die Anzahl im Text fest vor („ein Feld mit 20 Messwerten“).
Alle Elemente der Reihe nach anzusehen ist die Grundbewegung bei Feldern. Weil die Anzahl vorher feststeht, ist die Zählschleife aus Lektion 3 das passende Werkzeug. Der Zähler ist zugleich der Index:
Struktogramm
Pseudocode
FÜR i = 1 BIS n
AUSGABE zahlen[i]
ENDE FÜRFür das Feld oben werden nacheinander 4, 9, 2 und 7 ausgegeben. Jedes der folgenden Muster ist nichts anderes als dieser Durchlauf mit etwas Zusatz davor, im Rumpf und danach.
Summe und Durchschnitt
Das erste Muster: alle Werte zusammenzählen. Dafür braucht es eine Variable, die vor der Schleife auf 0 gesetzt wird und in jedem Durchlauf das aktuelle Element dazubekommt. Eine solche Variable heißt Akkumulator („Sammler“).
Struktogramm
Pseudocode
summe = 0
FÜR i = 1 BIS n
summe = summe + zahlen[i]
ENDE FÜR
AUSGABE summeDer Schreibtischtest (Wertetabelle) für zahlen = [4, 9, 2, 7] mit n = 4:
| Schritt | i | zahlen[i] | summe | Ausgabe |
|---|---|---|---|---|
| Start | · | · | 0 | · |
| summe = 0 + 4 | 1 | 4 | 4 | · |
| summe = 4 + 9 | 2 | 9 | 13 | · |
| summe = 13 + 2 | 3 | 2 | 15 | · |
| summe = 15 + 7 | 4 | 7 | 22 | · |
| Schleife beendet, Ausgabe | 5 | · | 22 | 22 |
Der Durchschnitt ist die Summe geteilt durch die Anzahl. Er kommt nach der Schleife dazu, als eine Anweisung. Wir setzen n >= 1 voraus (mindestens ein Wert), sonst würde durch 0 geteilt:
Struktogramm
Pseudocode
summe = 0
FÜR i = 1 BIS n
summe = summe + zahlen[i]
ENDE FÜR
durchschnitt = summe / n
AUSGABE durchschnittFür unser Feld: 22 / 4 = 5,5. Achte auf den Datentyp: durchschnitt muss eine Kommazahl sein, und die Division ist das / mit Nachkommastellen, nicht DIV. Mit ganzzahliger Division käme 5 heraus, und das ist in vielen Lösungshinweisen ein eigener Abzug. Wenn eine Aufgabe die Datentypen nennen lässt, schreibe „summe: Ganzzahl, durchschnitt: Kommazahl“ dazu.
Maximum und Minimum mit Index
Das größte Element finden: Du merkst dir einen Kandidaten und vergleichst jedes weitere Element mit ihm. Ist das Element größer, wird es der neue Kandidat. Oft will die Aufgabe nicht nur den Wert, sondern auch die Stelle, an der er steht; dann merkst du dir den Index gleich mit. Wir setzen n >= 1 voraus (mindestens ein Wert), damit der Startkandidat existiert.
Struktogramm
Pseudocode
max = zahlen[1]
pos = 1
FÜR i = 2 BIS n
WENN zahlen[i] > max DANN
max = zahlen[i]
pos = i
ENDE WENN
ENDE FÜR
AUSGABE max, pos| Prüfung | i | zahlen[i] | max | pos | Ausgabe |
|---|---|---|---|---|---|
| Start: max = zahlen[1] | · | · | 4 | 1 | · |
| 9 > 4: ja | 2 | 9 | 9 | 2 | · |
| 2 > 9: nein | 3 | 2 | 9 | 2 | · |
| 7 > 9: nein | 4 | 7 | 9 | 2 | · |
| Schleife beendet, Ausgabe | 5 | · | 9 | 2 | 9, 2 |
Das Minimum ist dieselbe Struktur mit umgedrehtem Vergleich: Der Kandidat wird ersetzt, wenn das Element kleiner ist.
Kommt der größte Wert mehrfach vor, behält > die erste Stelle, weil ein gleich großes Element die Bedingung nicht erfüllt. Mit >= würde die letzte Stelle gemerkt. Wenn die Aufgabe dazu nichts sagt, sind beide Varianten in Ordnung; sag im Zweifel in einem Satz dazu, welche du gewählt hast.
Zählen mit Bedingung
„Wie viele Werte sind größer als 5?“ Das Muster kennst du aus Lektion 4: ein Zähler, der vor der Schleife auf 0 gesetzt wird, und eine Verzweigung im Rumpf, in deren Ja-Zweig der Zähler um 1 erhöht wird. Neu ist nur, dass die Bedingung ein Feldelement prüft.
Struktogramm
Pseudocode
anzahl = 0
FÜR i = 1 BIS n
WENN zahlen[i] > 5 DANN
anzahl = anzahl + 1
ENDE WENN
ENDE FÜR
AUSGABE anzahl| Prüfung | i | zahlen[i] | anzahl | Ausgabe |
|---|---|---|---|---|
| Start | · | · | 0 | · |
| 4 > 5: nein | 1 | 4 | 0 | · |
| 9 > 5: ja | 2 | 9 | 1 | · |
| 2 > 5: nein | 3 | 2 | 1 | · |
| 7 > 5: ja | 4 | 7 | 2 | · |
| Schleife beendet, Ausgabe | 5 | · | 2 | 2 |
Der Unterschied zur Summe: Beim Zählen kommt in jedem Treffer + 1 dazu, bei der Summe + zahlen[i]. Beides lässt sich kombinieren, etwa „Summe aller geraden Werte“: Verzweigung mit zahlen[i] MOD 2 == 0, im Ja-Zweig summe = summe + zahlen[i].
Lineare Suche
„Kommt der Wert 2 im Feld vor, und wenn ja, an welcher Stelle?“ Die lineare Suche geht die Elemente von vorn nach hinten durch und vergleicht jedes mit dem gesuchten Wert. Zwei Dinge musst du dir merken: ob etwas gefunden wurde (ein Merker vom Typ Wahrheitswert) und wo (die Position). Sobald der Wert gefunden ist, darf die Suche aufhören. Deshalb ist die Standardform eine kopfgesteuerte Schleife mit doppelter Bedingung:
Struktogramm
Pseudocode
EINGABE gesucht
gefunden = falsch
i = 1
SOLANGE i <= n UND NICHT gefunden
WENN zahlen[i] == gesucht DANN
gefunden = wahr
position = i
ENDE WENN
i = i + 1
ENDE SOLANGE
WENN gefunden DANN
AUSGABE "Position", position
SONST
AUSGABE "nicht gefunden"
ENDE WENNDie Schleife läuft, solange noch Elemente übrig sind (i <= n) und noch nichts gefunden wurde (NICHT gefunden). Sobald eine der beiden Bedingungen kippt, endet sie: entweder am Feldende oder nach dem Treffer. Der Schreibtischtest für die Suche nach 2 in [4, 9, 2, 7]:
| Prüfung | i | zahlen[i] | gefunden | position | Ausgabe |
|---|---|---|---|---|---|
| Start: i = 1 | 1 | · | falsch | · | · |
| 1 <= 4 UND NICHT falsch: ja; 4 == 2: nein | 1 | 4 | falsch | · | · |
| 2 <= 4 UND NICHT falsch: ja; 9 == 2: nein | 2 | 9 | falsch | · | · |
| 3 <= 4 UND NICHT falsch: ja; 2 == 2: ja | 3 | 2 | wahr | 3 | · |
| 4 <= 4 UND NICHT wahr: nein, Schleife endet | 4 | · | wahr | 3 | · |
| gefunden: ja, Ausgabe | 4 | · | wahr | 3 | Position 3 |
Würde nach 5 gesucht, bliebe gefunden falsch, i liefe bis 5, die Bedingung 5 <= 4 wäre falsch, und die Ausgabe wäre „nicht gefunden“. Die Verzweigung nach der Schleife entscheidet über die Ausgabe; im Rumpf selbst wird nichts ausgegeben.
Die Alternative ist eine Zählschleife mit Merker. Sie ist kürzer, läuft aber nach dem Treffer bis zum Feldende weiter und merkt sich bei mehrfach vorkommenden Werten die letzte Position:
Merkregeln für alle Muster
- Startwert passend zum Muster: 0 für Summe und Zähler, 1 für ein Produkt, das erste Element für Maximum und Minimum,
falschfür den gefunden-Merker. - Eine Schleife über alle Elemente, der Zähler ist der Index. Grenzen zur Indexbasis passend: 1 bis n oder 0 bis n − 1.
- Ausgabe nach der Schleife, nicht im Rumpf. Im Rumpf wird nur gerechnet, verglichen und gemerkt.
Übungen
Führen Sie einen Schreibtischtest durch: Gegeben ist das Feld zahlen = [3, 8, 5, 8, 1]; das erste Element hat den Index 1. Welche Werte gibt das Struktogramm aus? Lege die Spalten i, zahlen[i], max und pos an und notiere zu jedem Durchlauf, ob die Bedingung zutrifft.
Musterlösung anzeigen
| Prüfung | i | zahlen[i] | max | pos | Ausgabe |
|---|---|---|---|---|---|
| Start: max = zahlen[1] | · | · | 3 | 1 | · |
| 8 > 3: ja | 2 | 8 | 8 | 2 | · |
| 5 > 8: nein | 3 | 5 | 8 | 2 | · |
| 8 > 8: nein | 4 | 8 | 8 | 2 | · |
| 1 > 8: nein | 5 | 1 | 8 | 2 | · |
| Schleife beendet, Ausgabe | 6 | · | 8 | 2 | 8, 2 |
Ausgabe: 8, 2. Die zweite 8 an Position 4 ändert nichts, weil 8 > 8 falsch ist; gemerkt bleibt die erste Fundstelle. Wer hier pos = 4 notiert, hat den Vergleich als >= gelesen.
Entwerfen Sie ein Struktogramm: Gegeben ist ein Feld zahlen mit n Werten; das erste Element hat den Index 1. Es soll ausgegeben werden, wie viele Werte über dem Durchschnitt aller Werte liegen. Überlege zuerst, was du wissen musst, bevor du zählen kannst.
Musterlösung anzeigen
Zwei Schleifen nacheinander: Die erste bildet die Summe, daraus entsteht der Durchschnitt, die zweite zählt. In einer einzigen Schleife geht es nicht, weil der Durchschnitt erst feststeht, wenn alle Werte gesehen wurden. Probe mit [4, 9, 2, 7]: Summe 22, Durchschnitt 5,5, darüber liegen 9 und 7, Ausgabe 2. Der Zähler i darf in beiden Schleifen gleich heißen, weil die erste Schleife beendet ist, bevor die zweite beginnt.
So wird typischerweise bewertet
- Erste Schleife über alle n Elemente bildet die Summe, Akkumulator vorher auf 0
- Durchschnitt nach der ersten Schleife als summe / n (Kommazahl)
- Zweite Schleife über alle Elemente mit Verzweigung zahlen[i] > durchschnitt
- Zähler vor der zweiten Schleife auf 0, Erhöhung im Ja-Zweig, Ausgabe nach der Schleife
- Gleichwertig: andere Schleifenart mit denselben Grenzen oder ein anderer Name für den zweiten Zähler; ein Zähler ab 0 nur mit Zugriff zahlen[i + 1]
Entwerfen Sie ein Struktogramm: In einem Feld kunden stehen n Kundennummern; das erste Element hat den Index 1. Eine Kundennummer wird eingegeben. Kommt sie im Feld vor, soll ihre Position ausgegeben werden, sonst der Text „nicht gefunden“. Die Suche soll nach dem ersten Treffer beendet werden.
Musterlösung anzeigen
Die kopfgesteuerte Schleife mit i <= n UND NICHT gefunden bricht nach dem Treffer ab. Der Merker startet mit falsch, die Position wird nur im Ja-Zweig gesetzt. Die Ausgabe hängt nach der Schleife am Merker, nicht an der Position, weil die Position bei Misserfolg gar keinen Wert hat. Probe: Für kunden = [1007, 1042, 1015] und gesucht = 1042 endet die Schleife nach dem zweiten Durchlauf mit Ausgabe „Position 2“; für 1099 läuft sie bis i = 4 durch und gibt „nicht gefunden“ aus.
So wird typischerweise bewertet
- Eingabe der gesuchten Nummer, Merker gefunden mit Startwert falsch
- Schleife über das Feld mit Vergleich kunden[i] == gesucht
- Im Ja-Zweig Merker auf wahr und Position gemerkt
- Ausgabe nach der Schleife per Verzweigung über den Merker: Position oder „nicht gefunden“
- Gleichwertig: Zählschleife mit Merker ohne Abbruch, oder eine Position mit Startwert 0 als Merker (0 heißt „nicht gefunden“)
Ergänzen Sie das Struktogramm an den Stellen (1) und (2): Es soll der kleinste Wert des Feldes zahlen mit n Elementen zusammen mit seiner Position ausgegeben werden; das erste Element hat den Index 1. Lücke (2) steht im Kopf der Verzweigung.
Musterlösung anzeigen
(1) min = zahlen[1]: der Startkandidat ist das erste Element, passend dazu steht schon pos = 1 darunter und die Schleife beginnt bei 2. (2) zahlen[i] < min: kleiner, nicht größer; zahlen[i] <= min ist ebenfalls richtig, dann gilt bei gleichen Werten die letzte Fundstelle. Probe mit [6, 3, 9, 3]: min startet mit 6; 3 < 6 ja (min = 3, pos = 2); 9 < 3 nein; 3 < 3 nein. Ausgabe 3, 2. Wer in (1) min = 0 schreibt, bekommt für dieses Feld die Ausgabe 0, 1, obwohl keine 0 im Feld steht.
Jetzt selbst testen
Vier Fragen zu Feldern und den Grundmustern.
Ein Feld hat n Elemente, das erste Element hat den Index 0. Wie lautet die Zählschleife über alle Elemente?
Welcher Startwert ist für die Suche nach dem Maximum sicher?
Aufgabentext: „Geben Sie aus, wie viele Bestellungen einen Wert über 100 Euro haben.“ Welches Muster ist gemeint?
Die lineare Suche läuft mit „solange i <= n UND NICHT gefunden“. Was bewirkt der zweite Teil der Bedingung?