type
TListNode =
class(TObject)
private
FNext:TListNode;
FPrev:TListNode;
public
procedure AfterConstruction();
override;
procedure BeforeDestruction();
override;
published
property Next:TListNode
read FNext;
property Prev:TListNode
read FPrev;
end;
TDoubleLinkedList =
class(TObject)
private
FHead:TListNode;
FTail:TListNode;
FSize:Integer;
protected
public
procedure AfterConstruction();
override;
procedure BeforeDestruction();
override;
procedure Append( Node:TObject );
procedure InsertBefore( Node, Before:TObject );
procedure Remove(
var Node:TObject; AndDelete:Boolean = False );
function NextNode( Node:TObject ):TObject;
function PrevNode( Node:TObject ):TObject;
procedure Clear();
published
property Size:integer
read FSize;
property Head:TListNode
read FHead;
property Tail:TListNode
read FTail;
end;
implementation
uses
SysUtils;
{ TListNode }
procedure TListNode.AfterConstruction();
begin
inherited;
FNext :=
nil;
FPrev :=
nil;
end;
procedure TListNode.BeforeDestruction();
begin
inherited;
end;
{ TDoubleLinkedList }
procedure TDoubleLinkedList.AfterConstruction();
begin
inherited;
FHead :=
nil;
FTail :=
nil;
FSize := 0;
end;
procedure TDoubleLinkedList.Clear();
var Node:TListNode;
begin
while FHead <>
nil do
begin
Node := FHead;
FHead := FHead.FNext;
Node.Free;
end;
end;
procedure TDoubleLinkedList.BeforeDestruction();
begin
Clear();
end;
procedure TDoubleLinkedList.Append( Node:TObject );
begin
if FHead =
nil then
begin
FHead := TListNode(Node);
FTail := TListNode(Node);
end else
begin
TListNode(Node).FPrev := FTail;
FTail.FNext := TListNode(Node);
FTail := TListNode(Node);
end;
Inc(FSize);
end;
procedure TDoubleLinkedList.InsertBefore( Node, Before:TObject );
begin
if FHead =
nil then
begin
FHead := TListNode(Node);
FTail := TListNode(Node);
end else
begin
if Before = FHead
then
begin
TListNode(Node).FNext := FHead;
FHead.FPrev := TListNode(Node);
FHead := TListNode(Node);
end else
begin
TListNode(Node).FNext := TListNode(Before);
TListNode(Node).FPrev := TListNode(Before).FPrev;
TListNode(Node).FPrev.FNext := TListNode(Node);
TListNode(Before).FPrev := TListNode(Node);
end;
end;
Inc(FSize);
end;
procedure TDoubleLinkedList.Remove(
var Node:TObject; AndDelete:Boolean );
begin
if Node =
nil then
begin
Exit;
end;
if Node = FHead
then
begin
FHead := FHead.FNext;
if FHead =
nil then
FTail :=
nil
else
FHead.FPrev :=
nil;
end
else if Node = FTail
then
begin
FTail := FTail.FPrev;
if FTail =
nil then
FHead :=
nil
else
FTail.FNext :=
nil;
end else
begin
TListNode(Node).FPrev.FNext := TListNode(Node).FNext;
TListNode(Node).FNext.FPrev := TListNode(Node).FPrev;
end;
Dec(FSize);
TListNode(Node).FNext :=
nil;
TListNode(Node).FPrev :=
nil;
// if AndDelete then
// begin
// TListNode(Node).Free();
// Node := nil;
// end;
end;
function TDoubleLinkedList.NextNode( Node:TObject ):TObject;
begin
if Node =
nil then
Result :=
nil
else
Result := TListNode(Node).FNext;
end;
function TDoubleLinkedList.PrevNode( Node:TObject ):TObject;
begin
if Node =
nil then
Result :=
nil
else
Result := TListNode(Node).FPrev;
end;