请大家帮我分析一下这个排序
短歌如风 2003-10-16 10:02:58 我对Quick Sort做了一些改进,主要方法是在把序列划分成两个子序列后,如果长子序列的长度超过短子序列的长度的二倍,则把长子序列平分成两个子序列分别排序然后合并。
此外就是取枢值和短序列使用插入排序。
我大致测试了一下,在“峰形”和“谷形”这两种对Quick Sort不利的分布时比Intro Sort要快。不过我想知道它的最差分布是什么,效率如何,请大家帮忙分析。
代码如下(Object Pascal):
procedure QuickSort(Data: PPointerList; Size: Integer; LessThen: TLessThenProc);//改进的QuickSort
var
M: Integer;
OtherData: PPointerList;
OtherSize: Integer;
begin
Assert(Data <> nil);
while Size > SORT_MAX do
begin
M := BinaryPart(Data, Size, LessThen);//用Quick Sort的逻辑划分子序列。
if (M < Size div 2) then
begin
OtherData := @Data[M];
OtherSize := Size - M;
Size := M;
end
else
begin
OtherData := Data;
OtherSize := M;
Data := @OtherData[M];
Size := Size - M;
end;
//<Data, Size>是短子序列,<OtherData, OtherSize>是较长子序列
M := OtherSize div 2;
if (M > Size) then
begin
QuickSort(OtherData, M, LessThen);
QuickSort(@OtherData[M], OtherSize - M, LessThen);
MergePart(OtherData, M, OtherSize, LessThen);
end
else
begin
QuickSort(OtherData, OtherSize, LessThen);
end;
end;
InsertionSort(Data, Size, LessThen);
end;
下面是用到的类型、常量定义和其它函数
type
TPointerList = array[0..32767] of Pointer;
PPointerList = ^TPointerList;
PPointer = ^ Pointer;
TLessThenProc = function(Left, Right: Pointer): Boolean;
TSortProc = procedure(Data: PPointerList; Size: Integer; LessThen: TLessThenProc);
TClockProc = function(): Double;
const
SORT_MAX:Integer = 16;
procedure Swap(var Left, Right: Pointer); overload;//交换两个指针
var
Temp:Pointer;
begin
Temp := Left;
Left := Right;
Right := Temp;
end;
procedure Swap(var Left, Right: Integer); overload;//交换两个整数
var
Temp: Integer;
begin
Temp := Left;
Left := Right;
Right := Temp;
end;
procedure SortInsert(Data: PPointerList; Size: Integer; Value: Pointer;
LessThen: TLessThenProc);//在已序序列中插入元素;用于插入排序和空间不足时的有序合并
var
J: Integer;
begin
if LessThen(Value, Data[0]) then
J := 0
else
begin
J := Size;
while (J > 0) and LessThen(Value, Data[J - 1]) do
begin
Dec(J);
end;
end;
Move(Data[J], Data[J +1], Sizeof(Pointer) * (Size - J));
Data[J] := Value;
end;
procedure SortMerge(SrcFirst, SrcSecond, Dest: PPointerList;
SizeFirst, SizeSecond: Integer; LessThen: TLessThenProc);//合并两个有序序列,目标和源无叠。
var
I: Integer;
begin
if (SizeFirst = 0) or (LessThen(SrcSecond[0], SrcFirst[0])) then
begin
Swap(Pointer(SrcFirst), Pointer(SrcSecond));
Swap(SizeFirst, SizeSecond);
end;
while SizeFirst > 0 do
begin
if SizeSecond = 0 then
I := SizeFirst
else
begin
I := 0;
while (I < SizeFirst) and not LessThen(SrcSecond[0], SrcFirst[I]) do
Inc(I);
end;
Move(SrcFirst^, Dest^, Sizeof(Pointer) * I);
Dec(SizeFirst, I);
SrcFirst := @SrcFirst[I];
Dest := @Dest[I];
Swap(Pointer(SrcFirst), Pointer(SrcSecond));
Swap(SizeFirst, SizeSecond);
end;
end;
procedure MergePart(Data: PPointerList; PartSize: Integer; Size: Integer;
LessThen: TLessThenProc);//把Data中的两个有序子序列合并成一个,空间不足时使用插入实现
var
Buffer: array of Pointer;
I: Integer;
begin
try
SetLength(Buffer, Size);
Move(Data^, Buffer[0], Size * Sizeof(Pointer));
SortMerge(@Buffer[0], @Buffer[PartSize], Data, PartSize, Size-PartSize, LessThen);
SetLength(Buffer, 0);
except
Dec(Size);
for I := PartSize to Size do
SortInsert(Data, I, Data[I], LessThen);
end;
end;
procedure InsertionSort(Data: PPointerList; Size: Integer;
LessThen: TLessThenProc);//简单插入排序
var
I, J: Integer;
Value: Pointer;
begin
Dec(Size);
for I := 1 to Size do
begin
SortInsert(Data, I, Data[I], LessThen);
end;
end;
function BinaryPart(Data: PPointerList; Size: Integer;
LessThen: TLessThenProc): Integer;//Quick Sort的一次迭代,划分子序列。
var
M: Integer;
Value: Pointer;
UnComplete: Boolean;
begin
M := Size shr 1;
Dec(Size);
if LessThen(Data[M], Data[0]) then
Swap(Data[0], Data[M]);
if LessThen(Data[Size], Data[M]) then
Swap(Data[Size], Data[M]);
if LessThen(Data[M], Data[0]) then
Swap(Data[0], Data[M]);
Value := Data[M];
Result := 0;
UnComplete := Size > Result;
while UnComplete do
begin
while LessThen(Data[Result], Value) do
Inc(Result);
while LessThen(Value, Data[Size]) do
Dec(Size);
UnComplete := Size > Result;
if UnComplete then
begin
Swap(Data[Result], Data[Size]);
Inc(Result);
Dec(Size);
end;
end;
end;