Autor Beitrag
Desert Storm
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 39



BeitragVerfasst: Di 10.10.06 20:15 
Hallo,
kann mir mal einer das Prinzip einer Liste erklären?
Also ich weiß wozu sie gut ist und sowas alles.
Ich hab aber Probleme mit dem Anker. Wie wird der Anker gesetzt und was is mit den ganzen anderen Zeigern? Sind die alle aufm Stack gespeichert?
Bitte um eine ganz genau erklärung vllt auch mit Code. Also eine ganz normale Liste. Wie man da in der Liste weiter gehen kann und auch Sachen aus der Liste löschen kann.
Alles nach dem FIFO Prinzip.
Danke
MFG
Marc.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1876
Erhaltene Danke: 129

Win 8.1, Xubuntu 15.10

BeitragVerfasst: Di 10.10.06 20:48 
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
[...]

// Vorwärtsdeklaration
//   Bei dieser Art der Deklaration zeigt zunächst ein Pointer auf den Typ TElement.
//   Erst anschließend wird dieser Typ definiert.
//   In der Definition enthalten, neben einigen Nutzdaten, ist ein weiterer Pointer, der   
//   wiederum auf PElement 'zeigt' - also auf das nächste Element!

type
  PElement = ^TElement;
  TElement = record
    text: string;
    next: PElement;
  end;

[...]

//Um uns merken zu können, wo unsere Liste beginnt, deklarieren wir einen weiteren Pointer, genannt Anker. Er wird das erste Element in der Liste sein und dieses auch bleiben.
//Um später zu wissen, wo wir sind, deklarieren wir noch einen weiteren Zeiger, genannt Aktuell.

var
 Anker: PElement;
 Aktuell: PElement; 
 S: String; // Dein Text

{******* Werte auf NIL setzen *******}

//Beim Aufrufen des Programmes, sind generell noch keine Elemente definiert, daher sind Anker und Akutell zunächst einmal NIL.
//(NIL = Not In List)

procedure TForm1.FormActivate(Sender: TObject);
begin
  anker := nil;
  aktuell := nil;
end;

{******* Speicher freigeben *******}

//Um hinterher auch alle Elemente der Liste beim Programmende wiederfreizugeben, "hangeln" wir uns von vorne (ab Anker) nach hinten, bis das das letzte Element ereicht ist und geben den Speicher wieder frei.
//Doch woher wissen wir, was das letzte Element ist? Ganz einfach, nachdem letzten Element folgt keines mehr, daher ist "next" NIL !

procedure TForm1.FormDeactivate(Sender: TObject);
var
  p, p_n: PElement;
begin
  p := anker;
  while p <> nil do
    begin
      p_n := p^.next;
      Dispose(p);
      p := p_n;
    end;
  anker := nil;
  aktuell := nil;
end;

{******* Neuer  Wert *******}

//Nun wollen wir doch auch einen Wert hinzufügen.
//Dazu deklarieren wir uns zwei Hilfzeiger, genannt p1 und p2.
//New(zeiger) reserviert für uns den Speicher, um hinterher auf diesenzugreifen zu können.
//Dispose(zeiger) gibt ihn hinterher wieder frei.
//Nun müssen wir zwischen zwei Fällen unterscheiden:
//1. Es liegt noch kein Element vor oder 2. es sind bereits Elemente definiert.
//Um herauszubekommen, welcher Fall uns vorliegt, prüfen wir einfach Anker auf "NIL", denn ist noch kein Element vorhanden, so ist dieser, wie bereits erwähnt, NIL.
//In diesem Falle müssen wir einfach nur Anker als erstes Element definieren: Anker := p1;
//Im anderen Falle wird es schon etwas komplizierter:
//Wir müssen uns vom ersten Element (Anker) wieder ganz nach vorne hangeln, und am Ende das Element anfügen. Das Element, nach dem hinzugefügten Element ist natürlich NIL, da nicht vorhanden.
//"Aktuell" ist nun natürlich das letzte Element.

procedure TForm1.New_Value;
var
  p1, p2: PElement;
begin
  New(p1);
  p1^.text := S;
  p1^.next := nil;

  if Anker = nil then
    anker := p1
  else
    begin
      p2 := anker;
      while (p2^.next <> nil) do
        p2 := p2^.next;
      p2^.next := p1;
    end;
  aktuell := p1;
end;

{*******  Ein Element löschen *******}

//Beim löschen unterscheiden drei Fälle:
//1. Das zu löschende Element ist der Anker, dabei müssen wir das nachdem Anker folgende Element als neuen Anker definieren und anschließend das aktuelle Element (aktuell = anker) freigeben.
//2. Das zu löschende Element ist mitten in der Liste:
//Dabei hangeln wir uns wie beim Rückwärtsgehen, von vorne bis nach eins vorm Aktuellen Element, und "überspringen" mithilfe von "p^.next := aktuell^.next" einfach das zu löschende Element. Anschließend geben wir Aktuell frei.
//3. Das zu löschende Element ist das letzte Element der Liste:
//Hier müssen wir uns wieder von Vorne nach Hinten hangeln und den nachfolger vom vorletzten Element als NIL definieren. Anschließend können wir das ursprünglich letzte Element freigeben.

procedure Delete;
var
  p: PElement;
begin
  if aktuell^.next = nil then
   begin
     p := anker;
     while (p <> nil) and (p^.next <> aktuell) do
        p := p^.next;
       p^.next := NIL;
       Dispose(aktuell);
       aktuell := p; 
    end else
    if aktuell = anker then
    begin
      anker := aktuell^.next;
      Dispose(aktuell);
      aktuell := anker;
    end
  else
    begin
      p := anker;
      while (p <> nil) and (p^.next <> aktuell) do
        p := p^.next;
      p^.next := aktuell^.next;
      Dispose(aktuell);
      aktuell := p;
    end;     
end;



{******* Forward *******}

//Wir wollen uns natürlich auch in der Liste bewegen. Um einen Schritt nach Vorne zu machen, lassen wir "Aktuell" einfach auf das nächste Element zeigen.
//Ist Aktuell allerdings bereits das letzte Element, d.h. Aktuell.next = NIL, können wir natürlich keinen Schritt weiter machen. Denn, man merke sich: ist ein Element NIL, als nicht in der Liste, können wir weder drauf schreiben noch lesen!

procedure TForm1.Forward;
begin
    if aktuell^.next <> nil then
      aktuell := aktuell^.next;
    S:= aktuell^.text
end;

{******* Backward *******}

//Etwas anders sieht es beim Rückwärtsgehen aus. 
//Wir hangeln uns von Vorne wieder nach Hinten, bis wir entweder das letzte Element erreicht haben oder eins vor dem Aktuellen angelant sind.

procedure TForm1.Backward;
var
  p: PElement;
begin
    p := anker;
    while (p <> nil) and (p^.next <> aktuell) do
      p := p^.next;

    if p <> nil then
      aktuell := p;
    S := aktuell^.text;
end;

end.


Mal flott getippt, hoffe des stimmt so alles ;)

Grüße,
Marc
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10185
Erhaltene Danke: 1261

W11x64
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 10.10.06 21:29 
Moin!

Am Ende dieses Beitrags ist ein Demo-Projekt zu linearen Listen. ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.