Claus SchönleberHitchhacker´s Guide To PASCAL [Vol. 2] |
||
|
[ Start | Beispielprogramme Download | Home ] | |
InhaltTypisierteKonstanten Sets (Mengen) Rekursion Records Dateien (Random Access) Pointer Algorithmen - Hashing - Sortieren |
SortierenIn Kurs 1 wurde schon einiges über das Sortieren gesagt. Am Beispiel des Verfahrens "Bubblesort" (Beispielprogramme) wurde gezeigt, wie man ein Feld auf einfache Weise in die gewünschte Reihenfolge ordnen kann. Die Grundoperation war Tauschen zweier Variablen (Feldelemente). Das Beispiel, da es eine Funktionsdemonstration ist, zeigt nicht, wie die Datensätze aussehen, die im Alltag zur Sortierung anstehen. Die können sehr viel komplexer sein, als die Zahlenliste im erwähnten Beispiel. Nehmen wir als Beispiel nur eine Personaldatei. Da besteht ein Datensatz aus Name, Vorname, Straße, Postleitzahl, Ort, Telefonnummer und vielen anderen Daten. Wenn die Tauschoperation hier ansetzen müßte, hätte das Programm nicht nur viel, sondern auch Unnötiges zu tun. Denn anstatt die Datensätze wirklich zu tauschen kann man sich ja notieren, wo sie eigentlich stehen müßten.Dieser Trick wird "indizierte Datei" oder manchmal auch, nicht exakt, "ISAM-Datei" (Indexsequentielle Datei) genannt. Er ist aber eine Vorstufe zur ISAM-Datei. Indizierte DateienUm eine zu sortierende Liste zu indizieren, benötigt man eine weitere Liste, in der die Indices (Positionen) der einzelnen Datensätze nach der Reihenfolge ihrer Eingabe eingetragen werden. Will man die Datensätze sortieren, so greift man beim Vergleich während des Sortierens nicht direkt auf die Datensätze zu, sondern über die in der Indexliste eingetragenen Positionen. Die Listen können Arrays sein (wie im Beispiel) oder auch Dateien. Dabei ist das indizierte Sortieren vom verwendeten Sortierverfahren unabhängig, denn die Indizierung regelt ja nur den Zugriffsmechanismus.Der Sortiervorgang. Da beim Sortieren die Datensätze nicht bewegt wurden, sieht die Liste selbst nach wie vor ungeordnet aus. Der Inhalt der Indexliste hat sich dabei aber verändert; wird die Indexliste jetzt nämlich der Reihe nach durchgesehen, findet man in jeder Komponente dieser Liste den Index des Datensatzes, der als nächster kommt. Damit ist die Liste sortiert, wenn man über diese Indexliste zugreift, sonst nicht!PROGRAM index_sort; TYPE person = RECORD name, vorname : STRING; gehalt : real; END; VAR data : ARRAY [1..10] OF person; index : ARRAY [1..10] OF integer; swapped : boolean; i : integer; PROCEDURE swap (VAR x,y : integer); VAR dummy : integer; BEGIN dummy := x; x := y; y := dummy; END; BEGIN (*** Initialisierung des Feldes durch Eingabe ***) (*** über die Tastatur ***) FOR i := 1 TO 10 DO BEGIN WITH data [i] DO BEGIN write ('Name: '); readln (name); write ('Vorname: '); readln (vorname); write ('Gehalt (DM): '); readln (gehalt); (*** Neuen Index in Indexliste eintragen ***) index [i] := i; END; END; (*** Sortieralgorithmus Bubblesort ***) REPEAT swapped := false; (* Flag initialisieren *) FOR i := 1 TO 9 DO BEGIN IF (data [index [i]] > data [index [i + 1]]) THEN BEGIN (*** Es wird jetzt der Index getauscht, ***) (*** nicht der Datensatz! ***) swap (index [i],index [i + 1]); swapped := true; END; END; UNTIL NOT swapped; (*** Ausgabe des sortierten Feldes ***) FOR i := 1 TO 10 DO writeln (data [index [i]]); END. Der Vorteil ist offensichtlich.
Zwei andere SortierverfahrenDamit Sie nicht nur auf Bubblesort angewiesen sind, sollen hier noch zwei weitere nicht allzu schwierige Algorithmen besprochen werden.DummsortDer Name ist von mir. Er läuft im Gegensatz zu Bubblesort eine konstante Zeit, also unabhängig vom Sortierungsgrad. Man könnte ihn als Mischung aus Bubblesort und "Direktem Auswählen" betrachten.Ausgehend von einer Liste mit n Elementen kann man folgendes Fragment formulieren: FOR i := 1 TO n - 1 DO FOR j := i + 1 TO n DO BEGIN IF a[i] > a[j] THEN swap (a[i],a[j]); END; Direktes Auswählen (Straight Selection)Es ist hier gleich als Prozedur formuliert, die sofort in ein Programm eingebunden werden kann ("feld" muß natürlich ein geeigneter Arraytyp sein). Es ist wesentlich schneller als Bubblesort und kann in Programmen durchaus als akzeptabel schnelle Sortierroutine verwendet werden.Für dieses Verfahren möchte ich auch gleich eine Version zum Sortieren von Random Access Dateien zeigen. Das Verfahren sortiert direkt auf der Platte. Ob Sie normal oder indiziert sortieren wollen, ist von Fall zu Fall zu entscheiden. Hier die normale Version. "workfiletype" ist eine Datei mit einem Recordtyp, der ein Feld "key", das Schlüsselfeld, enthält. Das ist der Name oder die Kundennummer. Es wird bei Bedarf anders genannt. In die Prozedur ist weiterhin ein Bildschirmteil eingebaut, der mit Hilfe einer einfachen Balkengraphik anzeigt, wieviel Prozent der Datei schon sortiert worden sind.PROCEDURE sort (VAR f : feld); VAR i,j,k,x : integer; BEGIN FOR i := 1 TO (n - 1) DO BEGIN k := i; x := f [i]; FOR j := (i + 1) TO n DO IF (f [j] < x) THEN BEGIN k := j; x := f [j]; END; f [k] := f [i]; f [i] := x; END; END; Der folgende Quelltext ist ein Fragment, das zu einem übersetzbaren Programm noch ergänzt werden muß: VAR workfiletype = FILE OF ....; str255 = STRING; PROCEDURE file_sort (VAR _file : workfiletype); CONST twentyblanks = ' '; VAR i,j,k,fs,p,ii,jj,kk : integer; ai,aj,ak,x : indexdata; w1,w2 : str255; (*** Um auch kleingeschriebenes richtig ***) (*** alphabetisch zu sortieren... ***) FUNCTION convert_up (x : str255) : str255; VAR i : integer; BEGIN FOR i := 1 TO length (x) DO x [i] := upcase (x [i]); convert_up := x; END; (*** of convert_up ***) BEGIN clrscr; writeln ('Datei wird sortiert...'); writeln; writeln; writeln (' 0 % 100'); writeln (' ------------------------------'); assign (_file,index_name); reset (_file); (*** Ermittle die Dateigröße ***) fs := filesize (indexfile); FOR i := 0 TO (fs - 2) DO BEGIN (*** Bildschirmzauber ***) (*** Angabe in Prozent... ***) write (^M,twentyblanks,(100 * i / fs):3:0,'%'); (*** Male den Balken entsprechend lang... ***) FOR p := 1 TO trunc (((100 * i) / fs) / 10) DO write ('*'); (*** Hier beginnt das Sortieren ***) k := i; (* x := a [i]; *) seek (_file,i); read (_file,ai); x := ai; FOR j := (i + 1) TO (fs - 1) DO BEGIN (* hole aj *) seek (_file,j); read (_file,aj); w1 := convert_up (aj.key); w2 := convert_up (x.key); IF (w1 < w2) THEN BEGIN k := j; (* x := a [j]; *) x := aj; END; END; (* a [k] := a [i]; *) seek (_file,k); write (_file,ai); (* a [i] := x; *) seek (_file,i); write (_file,x); END; close (_file); write (^M,twentyblanks,'100% '); FOR p := 1 TO 10 DO write ('[[['); gotoxy (29,20); write ('--- Taste drcken ---'); REPEAT UNTIL keypressed; clrscr; END; (*** of sort ***) Weiter Links zum Thema "Sortieren":
[Ende Teil 2]
|
|
|
(c) 2001 Schoenleber.com |