Contributor: MICHAEL DALES unit Lists; {--------------------------------------------------------------------------} { Abstract Data Type for dynamically sized list } { By Michael Dales 30th May 1996 } { } { Here is a simple list unit, that has the advantage of being dynamically } { sized, unlike normal arrays. To use the list you only need to know the } { data type names and the methods declared in the interface of this unit } { are used to manipulate them without the need to know the underlying } { representation. } { } { Deaclare your list variable to be of type TList, and remeber to use } { CreateList on it before you carry out any operations using it. Data is } { stored in nodes as pointers, just so you can have a list which isn't } { tied to just one kind of data type. Remeber though that because of this } { you'll need to typecast your pointers when you retrieve them from the } { list. Each node is has a type called PListNode, and an invalid node has } { the value null. } { } { Email comments to: 9402198d@udcf.gla.ac.uk } { URL: http://www.gla.ac.uk/Clubs/WebSoc/~9402198d/index.html } {--------------------------------------------------------------------------} interface const null = nil; {Non specific terminator} type PListNode = ^TListNode; {Pointer to node} TListNode = record {Node record} Item : Pointer; {Pointer to node data} Next : PListNode; {Next node} Previous : PListNode; {Previous node} end; TList = record {Holder for list} First : PListNode; {Pointer to start of list} Rear : PListNode; {Pointer to end of list} Size : integer; {Size of list} end; {CreateList - Initiates a new list} procedure CreateList(var L : TList); {DestroyList - Frees up all memory used by list and sets list to nil} procedure DestroyList(var L : TList); {AddNewNode - Adds new node to list L, filling it with the data supplied. Returns true is new node sucessfully added, otherwise returns false.} procedure AddNewNode(var L : TList; Data : Pointer); {DeleteListElement - Deletes an element passed.} procedure DeleteNode(var L : TList; ANode : PListNode); {GetFirstNode - Returns the first node in a given list} function GetFirstNode(L:TList):PListNode; {GetNextNode - Returns the successor of the given node} function GetNextNode(Node:PListNode):PListNode; {GetNodeData - Returns the data in a specific node} procedure GetNodeData(Node:PListNode; var Data:Pointer); {UpdateNode - Replaces a nodes details with new ones} procedure UpdateNode(Node:PListNode; Data:Pointer); {--------------------------------------------------------------------------} implementation {--------------------------------------------------------------------------} {CreateList - Initiates a new list} procedure CreateList(var L : TList); begin L.First := nil; {No list yet} L.Rear := nil; L.Size := 0; {No length yet} end; {RemoveLastNode - Deletes last node on the list} procedure RemoveLastNode(var L : TList); begin with L do {With the list} begin if Size > 0 then {If nodes in list} begin if Size = 1 then {If just one node} begin if First^.Item <> nil then {If data in node then} Dispose(First^.Item); {Dispose of it} Dispose(First); {Dispose of first node} First := nil; Rear := nil; {Set rear to nil} end else begin {If more than one node} Rear := Rear^.Previous; {Set rear to second last} Dispose(Rear^.Next); {Remove last node} end; Size := Size-1; {Decrement list size} end; end; end; {DestroyList - Frees up all memory used by list and sets list to nil} procedure DestroyList(var L : TList); begin while L.First <> nil do {While still nodes left} RemoveLastNode(L); {Remove last node} CreateList(L); end; {GetFirstNode - Returns the first node in a given list} function GetFirstNode(L : TList) : PListNode; begin GetFirstNode := L.First; end; {GetNextNode - Returns the successor of the given node} function GetNextNode(Node : PListNode) : PListNode; begin if Node <> nil then GetNextNode := Node^.Next else GetNextNode := nil; end; {GetNodeData - Returns the data in a specific node} procedure GetNodeData(Node : PListNode; var Data : Pointer); begin if Node <> nil then Data := Node^.Item else Data := nil; end; {AddNewNode - Adds new node to list L, filling it with the data supplied. Returns true is new node sucessfully added, otherwise returns false.} procedure AddNewNode(var L:TList; Data:Pointer); var temp : PListNode; begin new(temp); {Create new node} with temp^ do {Fill node} begin Item := Data; Next := nil; Previous := L.Rear; end; If (L.Size = 0) then {If empty list...} begin L.First := temp; {Add as first node} L.Rear := temp; end else {else add at end} begin L.Rear^.Next := temp; {Make old rear of list point to new} L.Rear := temp; {Make rear point to new node} end; L.Size := L.Size + 1; {Increment list length} end; {UpdateNode - Replaces a nodes details with new ones} procedure UpdateNode(Node : PListNode; Data : Pointer); begin if Node <> nil then begin Node^.Item := Data; end; end; {DeleteListElement - Deletes an element passed.} procedure DeleteNode(var L : TList; ANode : PListNode); begin if (L.Size = 1) or (ANode^.Next = nil) then {If we're deeling with} RemoveLastNode(L) {last node then that's easy} else {otherwise...} begin if (ANode = L.First) then {if we're deleting the first node} begin L.First := L.First^.Next; {Start list from second node} L.First^.Previous := nil; {Set new starts previous link} Dispose(ANode); {Dispose of old first} end else begin ANode^.Previous^.Next := ANode^.next; {Move pointers...} ANode^.Next^.Previous := ANode^.Previous; Dispose(ANode); {Dispose of node} end; L.Size := L.Size-1; {Note new list size} end; end; end.