Kurs 1613 Einführung in die imperative Programmierung 1 Aufgabe 1 In einer ersten for-schleife wird das Kandidatenfeld initialisiert, so dass alle Kandidaten hinten stehen. Eine zweite for-schleife simuliert die 50 Durchgänge des Auswahlverfahrens. Dabei werden im i-ten Durchlauf (i = 1,..., MAXKANDIDAT) jeweils mit einer inneren while-schleife die Vielfachen von i abgezählt, also die Kandidaten, die ihre Position ändern müssen, indem sievortreten, falls sie hinten stehen, bzw. zurücktreten, falls sie vorne stehen. Am Ende des Verfahrens stehen alle Kandidaten vorne, deren Nummern Quadratzahlen sind. procedure BerechneZustand ( outfeld : tkandidaten); { berechnet die zugelassenen und abgelehnten Kandidaten } i: tkandidatenbereich; {Durchlaeufe} j: tnatzahl; {Im i-ten Durchlauf werden hiermit die Kandidaten (Vielfache von i) abgezaehlt} { Initialisierung: alle Kandidaten stehen hinten } for i:= 1 to MAXKANDIDAT do outfeld[i] := hinten; { Durchlaeufe starten... } for i:= 1 to MAXKANDIDAT do j:=i; {erstes Vielfaches von i} while j <= MAXKANDIDAT do if outfeld[j] = vorn then outfeld[j] := hinten outfeld[j] := vorn; j := j + i; {naechstes Vielfaches von i} end; { while } end { for } end; { BerechneZustand } Aufgabe 2 Zur Lösung unseres Problems durchlaufen wir inliste1 mit den Zeigern Zeiger1 und ZeigHilf1 und inliste2 mit den Zeigern Zeiger2 und ZeigHilf2, wobei stets Zeiger1^.next=ZeigHilf1 und Zeiger2^.next=ZeigHilf2 gilt. Dabei ändern wir die Folgezeiger der Listenelemente, bis das Ende von inliste1 und damit von
2 Kurs 1613 Einführung in die imperative Programmierung inliste2 erreicht ist. Die angegebene Funktion arbeitet auch für den Fall ungleich langer Listen. Wir geben zusätzlich ein Rahmenprogramm an, welches den Test der Funktion Listen- Merge ermöglicht: program Aufgabe (input, output); { Testprogramm fuer die Funktion ListenMerge } type trefelement = ^telement; telement = record info : integer; next : trefelement end; tnatzahlplus = 1..maxint; Liste, Liste1, Liste2 : trefelement; Laenge : tnatzahlplus; function ListenMerge ( inliste1, inliste2 : trefelement) : trefelement; { fasst die Elemente der nicht-leeren und gleich langen Listen inliste1 und inliste2 mit dem Reissverschlussverfahren durch Aenderung der Verkettung zu einer einzigen Liste zusammen und gibt einen Zeiger auf den Anfang der Ergebnisliste zurück } Zeiger1, Zeiger2, ZeigHilf1, ZeigHilf2 : trefelement; Zeiger1 := inliste1; Zeiger2 := inliste2; while (Zeiger1 <> nil) and (Zeiger2 <> nil) do ZeigHilf1 := Zeiger1^.next; { 1) Nachfolger sichern } ZeigHilf2 := Zeiger2^.next; Zeiger1^.next := Zeiger2; { 2) Verkettung aendern } Zeiger2^.next := ZeigHilf1;
Kurs 1613 Einführung in die imperative Programmierung 3 Zeiger1 := ZeigHilf1; { 3) Zeiger weiterruecken } Zeiger2 := ZeigHilf2 end; ListenMerge := inliste1; { Neuen Anfang ausgeben } end; { ListenMerge } procedure ListeAufbauen ( inanz : tnatzahlplus; ioliste : trefelement ); { liest inanz Zahlen von der Tastatur ein und speichert sie in der Reihenfolge der Eingabe in der linearen Liste ioliste } Zahl : integer; AnfListe, EndListe, hilf : trefelement; k : tnatzahlplus; AnfListe := nil; writeln ('Bitte ', inanz, 'natuerliche Zahlen eingeben:'); for k := 1 to inanz do read (Zahl); new (hilf); hilf^.info := Zahl; hilf^.next := nil; if AnfListe = nil then { erste Zahl } AnfListe := hilf; EndListe := hilf end { zweite und weitere Zahlen } EndListe^.next := hilf; EndListe := hilf end end; ioliste := AnfListe end; { ListeAufbauen }
4 Kurs 1613 Einführung in die imperative Programmierung writeln ('Bitte die Listenlaenge eingeben (>0):'); readln (Laenge); ListeAufbauen (Laenge, Liste1); ListeAufbauen (Laenge, Liste2); Liste := ListenMerge (Liste1, Liste2); writeln ('Die "verkettete" Liste lautet:'); repeat write (Liste^.info); Liste := Liste^.next until Liste = nil end. { Aufgabe} Aufgabe 3 procedure NachVorn( inwert: integer; iorefanfang: trefelement); {Sucht das erste vorkommende Element mit inwert in der info-komponente und verschiebt dieses Element an den Anfang der Liste. ACHTUNG: Ein solches Element muss in der Liste vorkommen!} lauf, elem: trefelement; {Sonderfallprüfung: Falls das erste Element den Wert inwert hat, so ist nichts zu tun.} if (iorefanfang^.info <> inwert) then {Den Vorgaenger des zu verschiebenden Elementes suchen:} lauf := iorefanfang; while lauf^.next^.info <> inwert do lauf := lauf^.next; elem := lauf^.next; {elem zeigt nun auf das zu verschiebende Element, lauf auf dessen Vorgaenger. Jetzt verschieben:} lauf^.next := elem^.next; elem^.next := iorefanfang; iorefanfang := elem; end; {if} end; {NachVorn}
Kurs 1613 Einführung in die imperative Programmierung 5 Laut Aufgabenstellung durfte vorausgesetzt werden, dass der Suchwert in der Liste vorkommt, was insbesondere bedeutet, dass die Liste nicht leer sein kann, und dass, falls das Element nicht am Anfang steht, die Liste mindestens zwei Elemente hat. Die While-Bedingung oben ist also unter dieser Voraussetzung problemlos, es kann nicht zu einer Dereferenzierung von NIL kommen. Aufgabe 4 a) function countleaf(inrefwurzel : trefbinbaum ): tnatzahl; {die Funktion liefert die Anzahl der Blätter des inrefwurzel} if inrefwurzel = nil then countleaf := 0 if (inrefwurzel^.links = nil) and (inrefwurzel^.rechts = nil) then countleaf := 1 countleaf := countleaf(inrefwurzel^.links) + countleaf(inrefwurzel^.rechts); end; { countleaf }
6 Kurs 1613 Einführung in die imperative Programmierung b) 3 8 11 18 21 25 36 37 18 8 36 3 11 25 37 21 Aufgabe 5 Ein Testfall ist eine Menge von Testdaten, wobei ein Testdatum wiederum ein Paar ist, welches zum Ersten die Eingabedaten (hier: Eingabe für Parameter inzahl) und zum Zweiten die bei dieser Eingabe laut Spezifikation erwartete Ausgabe enthält: Abweisender Test: T 0 = { (0, 0) } Boundary-Test: T 1 = { (e, e) e {1,..., 9} } Interior-Test (2 Durchläufe): T 2 = { (e, a) e {10,..., 99} a ist die größere der zwei Ziffern von e}