program QuickSortTest;
{$MODE OBJFPC}{$LONGSTRINGS ON}
uses
HeapTrc;
type
TData = Integer;
PData = ^TData;
type
PNode = ^TNode;
TNode = record
Next: PNode;
Prev: PNode;
Data: PData;
end;
type
PList = ^TList;
TList = record
Head: PNode;
Tail: PNode;
end;
procedure SwapNodesData(var ALow, AHigh: PData);
var
Temp: PData;
begin
Temp := ALow;
ALow := AHigh;
AHigh := Temp;
end;
function GetPivotNode(ALow, AHigh: PNode): PNode;
var
Data: PData;
Left, Right: PNode;
begin
Data := AHigh^.Data;
Left := ALow^.Prev;
Right := ALow;
while Right <> AHigh do
begin
if Right^.Data^ < Data^ then
begin
if Left = nil then
Left := ALow
else
Left := Left^.Next;
SwapNodesData(Left^.Data, Right^.Data);
end;
Right := Right^.Next;
end;
if Left = nil then
Left := ALow
else
Left := Left^.Next;
SwapNodesData(Left^.Data, AHigh^.Data);
Result := Left;
end;
procedure QuickSortList(ALow, AHigh: PNode);
var
Pivot: PNode;
begin
if (AHigh <> nil) and (ALow <> AHigh) and (ALow <> AHigh^.Next) then
begin
Pivot := GetPivotNode(ALow, AHigh);
QuickSortList(ALow, Pivot^.Prev);
QuickSortList(Pivot^.Next, AHigh);
end;
end;
procedure CreateList(out AList: PList);
begin
New(AList);
AList^ := default(TList);
end;
procedure DisposeList(var AList: PList);
var
Current, Next: PNode;
begin
Current := AList^.Head;
while Current <> nil do
begin
Next := Current^.Next;
Dispose(Current^.Data);
Dispose(Current);
Current := Next;
end;
Dispose(AList);
AList := nil;
end;
procedure AddDataToList(AList: PList; AData: TData);
var
Fresh: PNode;
begin
New(Fresh);
New(Fresh^.Data);
Fresh^.Data^ := AData;
Fresh^.Next := nil;
if AList^.Head = nil then
begin
AList^.Head := Fresh;
AList^.Tail := Fresh;
AList^.Head^.Prev := nil;
end
else
begin
AList^.Tail^.Next := Fresh;
Fresh^.Prev := AList^.Tail;
AList^.Tail := Fresh;
end;
end;
procedure FillList(List: PList);
var
Index: Integer;
begin
for Index := 0 to 15 do
AddDataToList(List, Random(10));
end;
procedure PrintListFromHead(AList: PList);
var
Current: PNode;
begin
Current := AList^.Head;
while Current <> nil do
begin
Write(Current^.Data^:2);
Current := Current^.Next;
end;
WriteLn();
end;
procedure PrintListFromTail(AList: PList);
var
Current: PNode;
begin
Current := AList^.Tail;
while Current <> nil do
begin
Write(Current^.Data^:2);
Current := Current^.Prev;
end;
WriteLn();
end;
procedure PrintList(AList: PList; const ATitle: String);
begin
WriteLn(ATitle, LineEnding);
Write('from head:');
PrintListFromHead(AList);
Write('from tail:');
PrintListFromTail(AList);
WriteLn();
end;
var
List: PList;
begin
Randomize();
CreateList(List);
FillList(List);
PrintList(List, 'before sorting:');
QuickSortList(List^.Head, List^.Tail);
PrintList(List, 'after sorting:');
DisposeList(List);
end.