[Home |
Algorithmen] |
Zeigerverkettete Listen mit Pointern gelten oft als der Höhepunkt der Informatik in der Schule. Zweifellos gehört das Konzept zu den unverzichtbaren Inhalten. Über die Frage, ob im Unterricht harte Zeigerprobleme codiert werden müssen, gehen die Meinungen auseinander. Im Rahmen von OOP (jedenfalls, wenn alles Objekte sein sollen), kann man sich Zeigersemantik kaum vorstellen. JAVA als klassenbasierte Hochsprache kokettiert mit dem völligen Verzicht auf Pointer-Semantik wegen der relativen Gefährlichkeit. Da viele Probleme am elegantesten durch Zeiger-Strukturen gelöst werden können, wird das klassische Konzept Pointer-->Record durch Referenz-->Klasse gelöst, also durch eine selbstreferenzielle Assoziation des Elementtyps (rekursiv). Die nachfolgende rudimentäre Klasse Liste bildet in DELPHI die in Java übliche Programmierung nach. Der Typ TInhalt ist ein wenig 'dirty' und überflüssig, wenn man nur Objekte verwaltet, erlaubt aber auch beliebige Typen als Inhalt ohne weitere Anpassung des Codes oder Typcasting beim lesenden Zugriff. UNIT uRListe; (* ******************************************************************** *) (* K L A S S E : TElement, TListe *) (* -------------------------------------------------------------------- *) (* Version : 0.9 - Rohversion, nix abgefangen *) (* Autor : S. Spolwig, 2005 *) (* Beschreibung: uRListe vereint die Klassen TElement u. TListe als *) (* zeigerverkettetene lineare Liste, die zusammen *) (* betrachtet werden sollen. *) (* Die etwas merkwürdige Konstruktion ist der Versuch, *) (* ohne Pointer auszukommen, dabei aber die Grundsätze von*) (* OOP einzuhalten. Nach einer Anregung von D. Garmann, *) (* http://www.gymnasium-odenthal.de *) (* Compiler : Delphi 7.0 *) (* Aenderungen : 0.9 30-MAR-05 *) (* ******************************************************************** *) INTERFACE // ======================================================================= type TInhalt = TObject; // hier ändern für andere oder POINTER fuer alles // -------------------------------------------------------------------- TElement = class (TObject) private Inhalt : TInhalt; ZeigerNext, // Zeiger auf nächstes Element - kein POINTER! ZeigerPrev : TElement; // voriges public constructor Create (data : TInhalt); end; // -------------------------------------------------------------------- TListe = class (TObject) protected zFirstElememt, // der Ankerpunkt zActualElement : TElement; // wo man steht public constructor Create; procedure First; procedure Next ; procedure Last ; procedure Append (data : TInhalt); function GetInhalt : TInhalt; function GetLen : integer ; function IsEmpty : boolean; private end; (* -------------------- B e s c h r e i b u n g ------------------------- Oberklasse : Bezugsklassen : ........... import: Methoden -------- ... Get... Auftrag: Attribut aus dem Objekt lesen vorher : Objekt ist vorhanden nachher: - First Auftrag : Listenmarke (Zeiger) auf den Listenanfang setzen vorher : Die Liste ist vorhanden nachher : Aktuelle Position ist das 1. Element Ist die Liste leer , geschieht nichts ... --------------------------------------------------------------------- *) IMPLEMENTATION // ==================================================================== constructor TElement.Create (data : TInhalt); // -------------------------------------------------------------------- begin inherited Create; Inhalt := data; ZeigerNext := NIL; // dahinter kommt noch nix ZeigerPrev := NIL; end; // ==================================================================== constructor TListe.Create; // -------------------------------------------------------------------- begin inherited Create; zFirstElememt := NIL; // am Anfang leer zActualElement := NIL; end; procedure TListe.First; // -------------------------------------------------------------------- begin zActualElement := zFirstElememt; end; procedure TListe.Next ; // -------------------------------------------------------------------- begin if (NOT IsEmpty) AND (zActualElement.ZeigerNext <> NIL) then zActualElement := zActualElement.ZeigerNext; end; procedure TListe.Last; // -------------------------------------------------------------------- begin if (NOT IsEmpty) AND (zActualElement.ZeigerNext <> NIL) then begin zActualElement := zActualElement.ZeigerNext; Last; end; end; function TListe.IsEmpty : boolean; // -------------------------------------------------------------------- begin Result := (zFirstElememt = NIL); end; procedure TListe.Append (data : TInhalt); // -------------------------------------------------------------------- var NewElem : TElement; begin NewElem := TElement.Create(data); // neues El. erzeugen if IsEmpty then begin zFirstElememt := NewElem; zActualElement := NewElem; end else begin Last; zActualElement.ZeigerNext := NewElem; zActualElement := NewElem; end; end; function TListe.GetInhalt : TInhalt; // -------------------------------------------------------------------- begin Result := zActualElement.Inhalt; end; function TListe.GetLen : integer; // -------------------------------------------------------------------- var l : integer; zHilf : TElement; begin l := 0; zHilf := zFirstElememt; while zHilf <> NIL do begin zHilf := zHilf.ZeigerNext; inc(l); end; Result := l; end; // ------- usw. --- END. |