10. Fortgeschrittene Programmiertechniken Fortgeschrittene Programmiertechniken ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-1 10. Fortgeschrittene Programmiertechniken Zu den fortgeschrittenen Techniken gehören: ► Verwendung von komplexeren Datenstrukturen, z. B. von geschachtelten Strukturen, Baumstrukturen usw. ► Verwendung von vordefinierten und/oder standardisierten Algorithmen, z. B. Such- und Sortieralgorithmen ► Verwendung der Rekursion in Daten und Kontrollstrukturen ► Verwendung von speziellen Datenorganisationen, z. B. Hash-Tabellen und hash-Verfahren ► Verwendung von objektorientierten Programmiertechniken ► Softwareagenten-Technologien ► u. v. a. ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-2 10. Fortgeschrittene Programmiertechniken Geschachtelte Strukturen a) stufenweise Definition: #define STUD_ANZAHL 550 struct gruppe int int int } ; struct name { char char } ; { fachrichtung; semester; matrikelnummer; /* Komponenten */ nachname [20]; vorname [16]; ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-3 10. Fortgeschrittene Programmiertechniken struct geburtsdatum { int jahr; int monat; int tag; } ; struct student { /* Deklaration der Schablone "Student" struct gruppe bezeichnung; struct name familienname; struct geburtsdatum g_datum; } ; struct student tab_stud [STUD_ANZAHL]; /* Definition der Tabelle für Daten von Studenten */ */ ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-4 10. Fortgeschrittene Programmiertechniken b) „inline“ Definition: #define STUD_ANZAHL 550 struct student { struct gruppe { int fachrichtung; int semester; int matrikelnummer; } ; struct name { char nachname [20]; char vorname [16]; } ; struct geburtsdatum { int jahr; int monat; int tag; } } tab_stud [STUD_ANZAHL]; ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-5 10. Fortgeschrittene Programmiertechniken Zugriff zu den Komponenten (Beispiele): struct student *rn, *rq; struct name person_name; struct geburtsdatum dat; int geburtsjahr, geb_j2; char *surname; . . . /* Variablen für Demo */ rn = tab_stud; /* Adressenzuweisungen */ rq = &tab_stud[i]; person_name = (rn+i)->familienname; /* Wertzuweisungen */ dat = (rn+i)->g_datum; geburtsjahr = (rn+i)->g_datum.jahr; strcpy (surname, (rn+i)->familienname.nachname); geb_j2 = rq->g_datum.jahr /* oder rq = (*rq).datum.jahr */ ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-6 10. Fortgeschrittene Programmiertechniken Suchverfahren • direkte Suche • binäre Suche • Fibonacci Suche Merkmale „elementarer“ Suchverfahren • • • • Schlüssel sind eindeutig, d.h. es gibt keine Mehrfachtreffer Die Schlüsselmenge besitzt eine lineare Ordnung Es sind nur Schlüsselvergleiche erlaubt Ergebnis einer Suche ist das gefundene Item oder eine Fehlanzeige ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-7 10. Fortgeschrittene Programmiertechniken Direkte Suche • im Text int SearchTxt (char *s, char *p) { int n, m; // String - Musterlänge int i, j; // Suchzeiger unsigned int found; // Flag: 1 == gefunden, 0 == nicht gefunden n = strlen(s); m = strlen(p); for (i=0; i<n-m+1; i++) { found = 1; for (j=0; j<m; j++) if (s[i+j] != p[j]) found = 0; if (found == 1) return (i); } return(-1); } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-8 10. Fortgeschrittene Programmiertechniken • in Feldern // SearchSeq: Sequentielles Suchen in einem Array // Parameter: A Zahlenfeld, in dem gesucht wird // n Anzahl der gültigen Feldelemente // item gesuchtes Element //-------------------------------------------------------int SearchSeq (int *A, int n, int item) { int i; // Laufvariable A[0] = item; // Stopper-Element besetzen i = n + 1; // An das rechte Ende zeigen while (item != A[--i]); // Von rechts suchen return (i); // Index des Item oder 0 zurückliefern } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-9 10. Fortgeschrittene Programmiertechniken • in Tabellen int seq_search (int key, item *t, item *result, int p) /* Funktion seq_search für seq. Suche in der Tabelle t */ /* Parameter: key - Schlüssel der gesuchten Ware, t - Name der durchgesuchten Tabelle, result - Zeiger auf die Speicherzone, auf die das gesuchte Item /* abgespeichert werden soll, p - Länge der Tabelle */ Funktionswert: */ 0, wenn das Item gefunden war, -1, wenn nicht { int i; for (i=0; i<p; i++) if (t[i].num == key) { *result = t[i]; return (0); } return (-1); /* Variable für Indizes /* /* */ Item gefunden */ Item nicht gefunden */ } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-10 10. Fortgeschrittene Programmiertechniken Binäre Suche – Prinzip: Halbierung des Feldes Bedingung: Das durchgesuchte Feld muss geordnet werden! int bin_search (int key, item *t, item *result) /* Funktion bin_search für binäre Suche in der Tabelle t */ /* Parameter: key - Schlüssel der gesuchten Ware, t - Name der durchgesuchten Tabelle, result - Zeiger auf die Speicherzone */ /* Funktionswert: 0, wenn das Item erfolgreich gefunden, -1, wenn das Item nicht gefunden war */ { int m, left, right; /* Variablen für Indizes */ left = 0; /* Initialisierung von Suchgrenzen */ right = N-1; ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-11 10. Fortgeschrittene Programmiertechniken while (left<=right) { /* Ende - Bedingung m = (left+right) / 2; /* Mitte des Intervals if (t[m].num < key) left = m+1; /* Suche in der höheren Hälfte else if (t[m].num > key) right = m-1; /* in der unteren Hälfte else if (t[m].num == key) { *result = t[m]; /* Item gefunden return (0); } else return (-1); /* Item nicht gefunden } */ */ */ */ */ */ } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-12 10. Fortgeschrittene Programmiertechniken Fibonacci Suche – Prinzip: Aufteilung des Feldes nach Fibonacci Zahlen Bedingung: Das durchgesuchte Feld muss geordnet werden! ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-13 10. Fortgeschrittene Programmiertechniken Beispiel: ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-14 10. Fortgeschrittene Programmiertechniken Sortierverfahren • • • • direkte versus indirekte Verfahren interne versus externe Verfahren sequentielle versus parallele Verfahren fortgeschrittene und kombinierte Verfahren Merkmale „elementarer“ Sortierverfahren • Sie nutzen keine Eigenschaften der Datenstruktur aus • Sie verwenden als Operationen nur Schlüsselvergleiche und Transporte • Sie besitzen eine relativ hohe Komplexität – O(N2) • Komplexitätrelevante Operationen Vergleiche (Comparisons) Transport-Operationen (Movements) ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-15 10. Fortgeschrittene Programmiertechniken Beispiele elementarer Sortierverfahren: • • • • das Selection-Sort Verfahren das Insertion-Sort Verfahren das Shell-Sort Verfahren Das Bubble-Sort Verfahren Beispiele spezieller Sortierverfahren: • • • • das Quick-Sort Verfahren das Heap-Sort Verfahren das Merge-Sort Verfahren Das Radix-Sort Verfahren ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-16 10. Fortgeschrittene Programmiertechniken Beispiel – das Bubble-Sort Verfahren: /* ----------------------------------------------------/* Bubble Sort - Sortieren durch lokales Vertauschen /* ----------------------------------------------------void BubbleSort (elem F[], int L) { /* F ... das zu sortierende Feld von Items /* L ... Zahl von sortierten Feldelementen int j; elem Item; int XCHG; /* L ... /* "Zeiger" in die zu sortierende Liste /* Zwischenspeicher zum Vertauschen /* TRUE, wenn eine Vertauschung vorkam letzte Position der aktuellen Teilliste */ */ */ */ */ */ */ */ */ ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-17 10. Fortgeschrittene Programmiertechniken do { /* XCHG zeigt an, ob bei dieser Teilliste eine */ XCHG = 0; /* Vertauschung vorgenommen werden musste */ for (j=0; j<L; j++) /* aktuelle Teilliste durchlaufen,dabei vertauschen */ if (F[j].key > F[j+1].key) { Item = F[j]; /* Vertausch */ F[j] = F[j+1]; F[j+1] = Item; XCHG = 1; } L--; } while (XCHG); /* läuft solange zwei Elemente vertauscht wurden */ } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-18 10. Fortgeschrittene Programmiertechniken 2. Variante – mit Zeigern: void BubbleSort (elem *F, int L) /* F ... Zeiger auf das zu sortierende Feld von Items /* L ... Zahl von sortierten Feldelementen { elem *H; /* Zeiger auf das zu sortierende Feld elem Item; /* Zwischenspeicher zum Vertauschen int XCHG; /* TRUE, wenn eine Vertauschung vorkam /* L ... letzte Position der aktuellen Teilliste */ */ */ */ */ */ do { XCHG = 0; /* XCHG zeigt an, ob bei dieser Teilliste */ /* eine Vertauschung vorgenommen werden musste */ ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-19 10. Fortgeschrittene Programmiertechniken for (H=F; H<F+L; H++) /* aktuelle Teilliste /* durchlaufen und vertauschen if (H->key > (H+1)->key) { Item = *H; /* Vertausch *H = *(H+1); *(H+1) = Item; XCHG = 1; } L--; } while (XCHG); /* läuft solange zwei Elemente vertauscht wurden */ */ */ */ } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-20 10. Fortgeschrittene Programmiertechniken Beispiel – das Shell-Sort Verfahren: int shellsort (int v[], int n) /* v[0] .. v[n-1] aufsteigend sortieren { int gap, i, j, temp; for (gap = n/2; gap > 0; gap /= 2) for (i = gap; i < n; i++) for (j =i-gap; j>=0 && v[j]>v[j+gap]; j-=gap) { temp = v[j]; v[j] = v[j+gap]; /* Items wechseln v[j+gap] = temp; } */ */ } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-21 10. Fortgeschrittene Programmiertechniken Rekursion ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-22 10. Fortgeschrittene Programmiertechniken Rekursion • in Datenstrukturen (rekursiv definierte Strukturen) Listen L w1 w2 w3 w4 w5 Deklaration (Schablone): struct list_el { /* Struktur Listenelement int wert; struct list_el *next; } ; */ ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-23 10. Fortgeschrittene Programmiertechniken Bäume Kurt Franz Rolf Dieter Erich Hans Leo W Werner Karl ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-24 10. Fortgeschrittene Programmiertechniken Definition des Knotens: Kurt linker Sohn rechter Sohn Deklaration (Schablone): struct knoten { char *inhalt; /* diesmal Zeiger auf String */ struct knoten *links, *rechts; } ; ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-25 10. Fortgeschrittene Programmiertechniken • in Algorithmen (Programmen) Jedes Verfahren kann in allgemein folgendermaß definiert werden: P = ( Si , P ) Jeder rekursive Aufruf muss aber durch Erfüllung einer Bedingung beendet werden, d.h. P = if B then ( Si , P ), oder besser P = ( Si , if B then P ). ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-26 10. Fortgeschrittene Programmiertechniken Beispiel: Berechnung der Fakultät-Funktion long fak_rek (int n) { if (n > 1) return (n * fak_rek (n-1)); else return (n); } ohne Rekursion: long fak_it (int n) { int i; long f = 1; if (n > 1) { for (i=1; i<=n; i++) f *= i; return (f); } else return (n); } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-27 10. Fortgeschrittene Programmiertechniken Inhalt des Binärbaumes sortiert ausgeben: Definition: struct knoten { char *inhalt; /* diesmal Zeiger auf String */ struct knoten *links, *rechts; } *Baum; Algorithmus der Ausgabe: void Ausgeben (struct knoten *B) { if (B != NULL) { Ausgeben (B->links); printf ("%s, ", *(B->inhalt)); Ausgeben (B->rechts); } } /* Baum B ausgeben */ ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-28 10. Fortgeschrittene Programmiertechniken Hanoi – Türme: /********************************************************** * Türme von Hanoi: Ausgabe der Züge für diese Türme * **********************************************************/ void turm (char quelle, char hilf, char ziel, int k) { if (k==1) /* Ende der Rekursion */ printf (" %c -> %c\n", quelle, ziel); else { turm (quelle, ziel, hilf, k-1); printf (" %c -> %c\n", quelle, ziel); turm (hilf, quelle, ziel, k-1); } } ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-29 10. Fortgeschrittene Programmiertechniken Rekursives Sortierverfahren – Quick-Sort quicksort (int a[], int left, int int i, j, pivot, temp; i = left; j = right; pivot do { while (a[i] < pivot) i++; while (a[j] > pivot) j--; if (i <= j) { temp = a[i]; a[i] = a[j]; a[j] = temp; i++; j--; } } while (i <= j); if (left < j) quicksort (a, if (i < right) quicksort (a, } right) { /* aufsteigend sort. */ = a[(left+right)/2]; /* Items wechseln */ left, j); i, right); ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-30 10. Fortgeschrittene Programmiertechniken Zusammenfassung ► Verwendung von mehrfach strukturierten Datenobjekten sowie auch standardisierten Algorithmen und Methoden (Suchverfahren, Sortierverfahren usw.) vereinfacht das Schreiben von Programmen und erhöht ihre Übersichtlichkeit. ► Mehrheit von effizienten Suchalgorithmen (binäre Suche, Fibonacci-Suche u.v.a.) verlangt das Sortieren (Aneinanderreihung) des Suchraumes nach dem Suchschlüssel. ► Wenn die zu durchsuchenden Daten nach dem Schlüssel nicht sortiert sind, ist nur der Algorithmus der sequentiellen Suche zu verwenden. ► Direkte und indirekte Sortiermethoden sind zu verwenden. ► Direkte Methoden ändern die physische Aneinanderreihung von Daten, indirekte Methoden benutzen zur Aneinanderreihung verschiedene Hilfsstrukturen (Adressierungsvektoren oder -tabellen, verkettete Listen, Baumstrukturen usw.). ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-31 10. Fortgeschrittene Programmiertechniken ► Verwendung von Sortiermethoden ist vom Vorsortieren der zu sortierenden Datenfolgen abhängig. ► Verwendung der Rekursion vereinfacht wesentlich die Zerlegung von Verarbeitungsverfahren und die Erzeugung von Programmen. ► Es ist die Rekursion in Datenstrukturen und in Kontrollstrukturen (Programmen, Prozeduren, Funktionen, ...) zu unterscheiden. ► Rekursive Algorithmen und Programme sind sehr übersichtlich, aber ihre Verarbeitungskomplexität ist often höher, als bei den klassischen (sequentiellen oder iterativen) Programmstrukturen. ► Verwendung der Rekursion in Kontrollstrukturen (Programmen) ist meistens berechtigt, falls die benutzten Datenstrukturen auch rekursiv definiert werden (Algorithmen der Suche in Listen, Bäumen, usw.). ________________________________________________________________________________________________________________________________ V. Matoušek: Informationsverarbeitung / FH Regensburg 10-32