← Startseite
🧮

Vorlesung 9

Algorithmen Grundlagen I — Tauschen & Extremwerte

Grundlagen der Programmierung
Prof. Dr. Alexandra Mikityuk
HTW Berlin

Schleifenrichtung · Swap · Maximum · Minimum

🤔 Warum brauchen wir Algorithmen?

Ein Algorithmus ist eine Schritt-für-Schritt-Anleitung zur Lösung eines Problems.

Wie ein Kochrezept — aber für den Computer.

Heute lernen wir vier Bausteine:

🔄 Werte tauschen (Swap)

Wie tauscht man zwei Variablen, ohne den ersten Wert zu verlieren?

📊 Schleifen: auf- vs. abwärts

Wann zählt man vorwärts, wann rückwärts — und warum?

⬆️ Maximum finden

Größtes Element in einem Array systematisch ermitteln.

⬇️ Minimum finden

Spiegelbild des Maximums — fast identisches Muster.

🔁 Schleifen — aufwärts oder abwärts?

Wann zählen wir aufwärts, wann abwärts? Hängt vom Problem ab.

⬆️ Aufwärts (0 → n)

for (int i = 0; i < n; i++)
{
    // Von Anfang bis Ende
}
  • Standard für Arrays durchlaufen
  • Summe berechnen
  • Elemente zählen

⬇️ Abwärts (n → 0)

for (int i = n - 1; i >= 0; i--)
{
    // Von Ende bis Anfang
}
  • Array umgekehrt ausgeben
  • Countdown
  • Elemente löschen

⬆️ Beispiel — aufwärts zählen

#include <stdio.h>

int main()
{
    int zahlen[5] = {10, 20, 30, 40, 50};

    printf("Array vorwärts:\n");
    for (int i = 0; i < 5; i++)
    {
        printf("zahlen[%d] = %d\n", i, zahlen[i]);
    }

    return 0;
}

Output

Array vorwärts: zahlen[0] = 10 zahlen[1] = 20 zahlen[2] = 30 zahlen[3] = 40 zahlen[4] = 50
Merkmal: Index startet bei 0, Bedingung i < 5, Erhöhung i++ — Standardmuster für Array-Durchlauf.

⬇️ Beispiel — abwärts zählen

#include <stdio.h>

int main()
{
    int zahlen[5] = {10, 20, 30, 40, 50};

    printf("Array rückwärts:\n");
    for (int i = 4; i >= 0; i--)
    {
        printf("zahlen[%d] = %d\n", i, zahlen[i]);
    }

    return 0;
}

Output

Array rückwärts: zahlen[4] = 50 zahlen[3] = 40 zahlen[2] = 30 zahlen[1] = 20 zahlen[0] = 10
Achtung: Bedingung ist i >= 0 (nicht i > 0) — sonst wird Element [0] übersprungen.

🚀 Praktisch — Countdown

#include <stdio.h>

int main()
{
    printf("Raketenstart!\n\n");

    /* Countdown von 10 bis 1 */
    for (int i = 10; i >= 1; i--)
    {
        printf("%d...\n", i);
    }

    printf("\n🚀 LIFTOFF!\n");

    return 0;
}

Output

Raketenstart! 10... 9... 8... ... 1... 🚀 LIFTOFF!
Typischer Use-Case: Abwärts-Schleifen passen perfekt, wenn die Zählung selbst Teil der Ausgabe ist.

🔄 Das Tausch-Problem

Wie tauschen wir die Werte von zwei Variablen?

5a
3b

⚠️ Das funktioniert NICHT

a = b;    // a ist jetzt 3, aber 5 ist verloren!
b = a;    // b ist auch 3 — beide sind gleich!

Problem: Der ursprüngliche Wert von a wird überschrieben, bevor wir ihn speichern können.

Schlüssel-Idee: Wir brauchen einen Zwischenspeicher — eine dritte Variable, die den Wert rettet.

💡 Die Lösung — die Hilfsvariable

Drei Schritte, wie beim Umräumen von Gläsern:

Schritt 1 · temp = a
5a
3b
5temp
Schritt 2 · a = b
3a
3b
5temp
Schritt 3 · b = temp
3a
5b
5temp
Ergebnis: a und b sind getauscht — und kein Wert ging verloren.

🔄 Swap im Code

#include <stdio.h>

int main()
{
    int a = 5;
    int b = 3;
    int temp;

    printf("Vorher: a = %d, b = %d\n", a, b);

    /* Tauschen mit Hilfsvariable */
    temp = a;    // 1. Wert von a sichern
    a = b;       // 2. b nach a kopieren
    b = temp;    // 3. Gesicherten Wert nach b

    printf("Nachher: a = %d, b = %d\n", a, b);

    return 0;
}

Output

Vorher: a = 5, b = 3 Nachher: a = 3, b = 5
✅ Merke: Swap braucht immer 3 Schritte und eine Hilfsvariable.

🔄 Swap in Arrays

Das gleiche Prinzip funktioniert auch mit Array-Elementen — nur die Namen sehen anders aus.

#include <stdio.h>

int main()
{
    int zahlen[5] = {10, 20, 30, 40, 50};
    int temp;

    printf("Vorher: %d %d %d %d %d\n",
        zahlen[0], zahlen[1], zahlen[2], zahlen[3], zahlen[4]);

    /* Element 0 und Element 4 tauschen */
    temp = zahlen[0];
    zahlen[0] = zahlen[4];
    zahlen[4] = temp;

    printf("Nachher: %d %d %d %d %d\n",
        zahlen[0], zahlen[1], zahlen[2], zahlen[3], zahlen[4]);

    return 0;
}

Output

Vorher: 10 20 30 40 50 Nachher: 50 20 30 40 10
Ausblick: Genau dieses Muster brauchen wir gleich für Sortier-Algorithmen — z.B. Bubble Sort tauscht Nachbarn so lange, bis alles sortiert ist.

⬆️ Maximum finden — Problem + Idee

Wie finden wir die größte Zahl in einem Array?

7[0]
3[1]
12[2]
5[3]
9[4]

💡 Die Idee in 4 Schritten

  1. Nimm das erste Element als „bisheriges Maximum"
  2. Gehe durch alle weiteren Elemente
  3. Wenn ein Element größer ist → neues Maximum merken
  4. Am Ende der Schleife steht das Maximum fest

⬆️ Maximum — Schritt für Schritt

Mit dem Array {7, 3, 12, 5, 9} — was passiert in jedem Schritt?

SchrittElementVergleichmax
Startzahlen[0] = 77
i = 1zahlen[1] = 33 > 7? ❌ Nein7
i = 2zahlen[2] = 1212 > 7? ✅ Ja12
i = 3zahlen[3] = 55 > 12? ❌ Nein12
i = 4zahlen[4] = 99 > 12? ❌ Nein12
Ende12 ✓
Beobachtung: Das Maximum wird nur dann aktualisiert, wenn ein größerer Wert gefunden wird — sonst bleibt es einfach stehen.

⬆️ Maximum — der Code

#include <stdio.h>

int main()
{
    int zahlen[5] = {7, 3, 12, 5, 9};
    int max;

    /* Erstes Element als Startwert */
    max = zahlen[0];

    /* Alle weiteren Elemente prüfen */
    for (int i = 1; i < 5; i++)
    {
        if (zahlen[i] > max)
        {
            max = zahlen[i];
        }
    }

    printf("Das Maximum ist: %d\n", max);

    return 0;
}

Output

Das Maximum ist: 12

🔍 Schlüssel-Zeilen

max = zahlen[0] — Startwert
i = 1 — Schleife startet bei 1 (s. nächste Folie)
if (… > max) — Vergleich + Update

❓ Warum beginnt die Schleife bei i = 1?

⚠️ Nur beim Min/Max-Algorithmus! Bei anderen Algorithmen (Array ausgeben, Summe berechnen) startet ihr weiterhin bei i = 0.

Der Grund: Wir setzen max = zahlen[0] vor der Schleife als Startwert. Element [0] wurde also schon „verwendet" — es wäre sinnlos, zahlen[0] > zahlen[0] zu prüfen.

Effizient — Start bei i = 1

max = zahlen[0];   // Index 0 ist Startwert
for (int i = 1; i < n; i++)  // Ab Index 1

n − 1 Vergleiche (optimal)

😐 Auch korrekt — Start bei i = 0

max = zahlen[0];
for (int i = 0; i < n; i++)  // Prüft auch [0]

n Vergleiche (1 unnötig: zahlen[0] > zahlen[0])

⬇️ Minimum finden

Fast identisch zum Maximum — nur das Vergleichszeichen ändert sich!

#include <stdio.h>

int main()
{
    int zahlen[5] = {7, 3, 12, 5, 9};
    int min;

    /* Erstes Element als Startwert */
    min = zahlen[0];

    /* Alle weiteren Elemente prüfen */
    for (int i = 1; i < 5; i++)
    {
        if (zahlen[i] < min)   // Nur dieses Zeichen!
        {
            min = zahlen[i];
        }
    }

    printf("Das Minimum ist: %d\n", min);

    return 0;
}

Output

Das Minimum ist: 3
Das Muster: Min/Max sind dasselbe Algorithmus-Skelett — Startwert + Schleife + Vergleich. Tauscht ><, fertig.

📊 Min UND Max gleichzeitig

Eine Schleife, zwei Ergebnisse — keine Doppelarbeit nötig.

#include <stdio.h>

int main()
{
    int zahlen[5] = {7, 3, 12, 5, 9};
    int min, max;

    /* Beide mit erstem Element initialisieren */
    min = zahlen[0];
    max = zahlen[0];

    for (int i = 1; i < 5; i++)
    {
        if (zahlen[i] < min)
            min = zahlen[i];

        if (zahlen[i] > max)
            max = zahlen[i];
    }

    printf("Minimum: %d\n", min);
    printf("Maximum: %d\n", max);
    printf("Spannweite: %d\n", max - min);

    return 0;
}

Output

Minimum: 3 Maximum: 12 Spannweite: 9
Effizienz: Statt zweier separater Schleifen reicht eine — beide Tests pro Iteration. Spart Laufzeit ohne Komplexitätsverlust.

📍 Position des Maximums finden

Manchmal brauchen wir nicht den Wert, sondern wo er steht — wir merken uns den Index.

#include <stdio.h>

int main()
{
    int zahlen[5] = {7, 3, 12, 5, 9};
    int maxPos = 0;   // Position des Maximums

    for (int i = 1; i < 5; i++)
    {
        if (zahlen[i] > zahlen[maxPos])
        {
            maxPos = i;   // Neue Position merken
        }
    }

    printf("Maximum %d steht an Position %d\n",
        zahlen[maxPos], maxPos);

    return 0;
}

Output

Maximum 12 steht an Position 2
Trick: Statt den Wert zu speichern, speichern wir den Index. Den Wert holen wir uns mit zahlen[maxPos] jederzeit.

📝 Praxis — beste und schlechteste Note

Achtung: Bei Schulnoten ist kleinere Note = besser (1 = sehr gut, 6 = ungenügend).

#include <stdio.h>

int main()
{
    int noten[6] = {2, 1, 3, 2, 4, 1};
    int beste = noten[0];
    int schlechteste = noten[0];

    for (int i = 1; i < 6; i++)
    {
        if (noten[i] < beste)        // Kleinere Note = besser
            beste = noten[i];
        if (noten[i] > schlechteste) // Größere Note = schlechter
            schlechteste = noten[i];
    }

    printf("Beste Note: %d\n", beste);
    printf("Schlechteste Note: %d\n", schlechteste);

    return 0;
}

Output

Beste Note: 1 Schlechteste Note: 4
Wichtig: „Min" und „Max" sind mathematisch, nicht semantisch. Was „besser" heißt, hängt vom Kontext ab — bei Noten ist Min die beste, bei Punktzahlen ist Max die beste.

🎯 Bonus — Noten klassifizieren mit switch / case

Wir haben das Noten-Array — jetzt wollen wir für jede Note auch den Text ausgeben. Klassischer Fall für switch / case: ein Wert wird auf mehrere mögliche Zustände abgebildet.

#include <stdio.h>

int main()
{
    int noten[6] = {2, 1, 3, 2, 4, 1};

    for (int i = 0; i < 6; i++)
    {
        printf("Note %d: ", noten[i]);

        switch (noten[i])
        {
            case 1: printf("sehr gut\n");      break;
            case 2: printf("gut\n");           break;
            case 3: printf("befriedigend\n");  break;
            case 4: printf("ausreichend\n");   break;
            case 5: printf("mangelhaft\n");    break;
            case 6: printf("ungenügend\n");    break;
            default: printf("unbekannt\n");    break;
        }
    }

    return 0;
}

Output

Note 2: gut Note 1: sehr gut Note 3: befriedigend Note 2: gut Note 4: ausreichend Note 1: sehr gut
Warum hier switch statt if / else if? Bei vielen festen Werten (1, 2, 3, …) liest sich switch klarer. Jedes break beendet den passenden Fall — ohne break würde der nächste Fall auch ausgeführt (Fall-Through).

⚖️ switch vs. if / else if — wann was?

Dieselbe Note-Klassifikation in beiden Schreibweisen — wann ihr was nehmt:

switch / case

switch (note)
{
    case 1: ...; break;
    case 2: ...; break;
    case 3: ...; break;
    default: ...;
}

Stark, wenn:

  • Vergleich gegen feste Werte (int, char)
  • Viele Fälle (≥ 3-4)
  • Compiler optimiert oft schneller

🆗 if / else if

if (note == 1) ...;
else if (note == 2) ...;
else if (note == 3) ...;
else ...;

Stark, wenn:

  • Vergleich mit Bereichen (note < 4)
  • Mehrere Variablen gleichzeitig
  • Komplexe Bedingungen (UND / ODER)
⚠️ Falle: Fehlt das break, läuft der Code in den nächsten case weiter („Fall-Through"). Manchmal gewollt — meistens ein Bug. Immer prüfen.
Faustregel: Festwert-Dispatch → switch. Bereiche oder komplexe Logik → if / else if.

🧠 Quiz — Swap

Was ist der Wert von a und b nach diesem Code?

int a = 10, b = 20, temp;
temp = a;
a = b;
b = temp;
Aa = 10, b = 20
Ba = 20, b = 10
Ca = 20, b = 20
Da = 10, b = 10

✅ Lösung — Swap

Ba = 20, b = 10 — die Werte wurden erfolgreich getauscht.

Schritt für Schritt

Zeileabtemp
Anfang1020?
temp = a102010
a = b202010
b = temp201010

🧠 Quiz — Maximum

Was gibt dieses Programm aus?

int arr[4] = {5, 5, 5, 5};
int max = arr[0];
for (int i = 1; i < 4; i++) {
    if (arr[i] > max) max = arr[i];
}
printf("%d", max);
A0
B4
C5
D20

✅ Lösung — Maximum

C5 — alle Elemente sind gleich, also bleibt das Maximum 5.

💡 Warum?

  • max = arr[0] → max wird 5
  • Schleife prüft: 5 > 5? → Nein, also bleibt max bei 5
  • Das funktioniert auch bei allen gleichen Werten — der Algorithmus ist robust

🧠 Quiz — Schleifenrichtung

Welche Ausgabe erzeugt diese Schleife?

for (int i = 3; i >= 1; i--)
{
    printf("%d ", i);
}
A1 2 3
B3 2 1
C3 2 1 0
D0 1 2 3

✅ Lösung — Schleifenrichtung

B3 2 1

Ablauf

ii >= 1?AusgabeDanach
3✅ Ja3i-- → 2
2✅ Ja2i-- → 1
1✅ Ja1i-- → 0
0❌ NeinSchleife endet

📋 Zusammenfassung — Swap

🔄 Standard-Swap

/* Hilfsvariable + 3 Schritte */
int temp = a;
a = b;
b = temp;

✅ Eigenschaften

  • Immer 3 Schritte
  • Hilfsvariable temp nötig
  • Funktioniert für alle Datentypen
  • Baustein für Sortier-Algorithmen
Merksatz: Erst sichern, dann überschreiben — nie direkt zuweisen.

📋 Zusammenfassung — Min / Max

⬆️ Maximum

max = arr[0];
for (i = 1; i < n; i++)
    if (arr[i] > max)
        max = arr[i];

⬇️ Minimum

min = arr[0];
for (i = 1; i < n; i++)
    if (arr[i] < min)
        min = arr[i];

💡 Das gemeinsame Muster

  1. Erstes Element als Startwert nehmen
  2. Alle weiteren Elemente durchgehen (ab i = 1)
  3. Bei besserem Wert → aktualisieren

📋 Zusammenfassung — Schleifenrichtung

⬆️ Aufwärts (Standard)

for (i = 0; i < n; i++)
  • Array durchlaufen
  • Summe berechnen
  • Elemente zählen
  • Min / Max finden

⬇️ Abwärts (Speziell)

for (i = n-1; i >= 0; i--)
  • Rückwärts ausgeben
  • Countdown
  • Elemente entfernen
  • Palindrom prüfen
⚠️ Achtung bei Abwärts: Die Bedingung ist i >= 0 (nicht i > 0) — sonst wird Element [0] übersprungen.

🔮 Nächste Vorlesung — Algorithmen Grundlagen II

Akkumulieren — wie Werte über eine Schleife zusammenkommen

  • ➕ Summe berechnen
  • 📊 Durchschnitt berechnen
  • 🔢 Elemente zählen
  • ✖️ Produkt berechnen
  • 🎯 Kombinierte Muster (z.B. „nur positive Zahlen mitteln")
Heute gelernt: Swap · Maximum · Minimum · Schleifenrichtungen. Diese Bausteine brauchen wir für fast jeden Algorithmus.
1 / 28