您的位置:首页 > 编程语言 > Delphi

【Delphi】对 QuickSort 函数的理解

2012-01-01 16:14 330 查看
在 Delphi 的 Classes 单元定义了 TList 类,TList 有一个 Sort 方法,用来对 TList 里面的指针数组进行排序,这个方法调用了 QuickSort 函数,这个函数不好理解,我看了很久才看明白。记录下来,以免将来忘记了。

{ 对指针进行排序,Compare 为排序函数 }
procedure TList.Sort(Compare: TListSortCompare);
begin
if (FList <> nil) and (Count > 1) then
{ 调用 Compare 进行排序 }
QuickSort(FList, 0, Count - 1,
function(Item1, Item2: Pointer): Integer
begin
Result := Compare(Item1, Item2);
end);
end;

TListSortCompare = function (Item1, Item2: Pointer): Integer;

{ 快速排序过程 }
{ SortList:指针数组
L:排序范围的最左边(头)
R:排序范围的最右边(尾)
SCompare:比较两个指针所指内容大小的函数 }
procedure QuickSort(SortList: PPointerList; L, R: Integer;
SCompare: TListSortCompareFunc);
var
I, J: Integer; { 用来移动并查找元素的位置值 }
P, T: Pointer; { 存放中间元素和临时元素 }
begin
repeat
{ 设定刚开始查找时的起始位置 I 和结束位置 J }
I := L;  { 最小 Index }
J := R;  { 最大 Index }
{ 获取范围正中间的元素 P 的值 }
{ (L + R) shr 1 相当于 (L + R) div 2 }
P := SortList^[(L + R) shr 1];
repeat
{ 从 I 开始向后找比 P 大(>=)的元素 }
while SCompare(SortList^[I], P) < 0 do
Inc(I);
{ 从 J 开始向前找比 P 小(<=)的元素 }
while SCompare(SortList^[J], P) > 0 do
Dec(J);
{ 判断 I 和 J 是否碰过头(I > J 就表示已经碰过头了) }
{ 刚碰头不算,碰头后继续走一步才算碰过头 }
if I <= J then
begin
{ 如果还没有碰头,则交换 I 和 J 的元素值,小的排前面,大的排后面 }
{ 如果 I 和 J 刚碰头并且都指向同一个元素(I = J),则没必要自己和自己交换 }
if I <> J then
begin
T := SortList^[I];
SortList^[I] := SortList^[J];
SortList^[J] := T;
end;
{ I 和 J 各自向各自方向走一步,继续比较下一个元素 }
Inc(I);
Dec(J);
end;
{ 如果已经碰过头,则退出此轮循环 }
{ 此时应该是 I := J + 1,即:I 在 J 的后面,并且紧挨着 J }
until I > J;
{ 经过这样的一轮循环,此时 J 前面的元素全部都小于等于 P,J 后面的元素全部都大于等于 P,与 P 相等的元素(重复出现的元素,等 P 元素)会在 J 的前后换来换去,位置不定,不过没关系,将来 J 前面的一串元素(串1)会作为一个整体再次排序,那么与 P 相等的元素(等 P 元素)就会排在串后(串1的最后),而 J 后面的一串元素(串2)也会作为一个整体再次排序,那么与 P 相等的元素(等 P 元素)就会排在串前(串2的前面),这样两串元素(“串1”与“串2”)在 J 的位置相连接,就把所有与 P 相等的元素(等 P 元素)连在一起了 }

{ L < J 表示 J 前面还有元素需要排序,这些元素也就是上面所说的小于 P 的元素,(也就是“串1”) }
{ 递归调用 QuickSort 函数对“串1”进行排序 }
if L < J then
QuickSort(SortList, L, J, SCompare);
{ 经过一层或多层递归处理后,“串1”已经被全部排序完毕,接下来就要处理 J 后面的元素了,也就是“串2” }

{ 此时 I 刚好在 J 的后面紧挨着 J,所以从 I 开始后面元素的为“串2” }
{ 将 I 作为范围的起始位置,范围的结束位置不变,继续处理“串2” }
L := I;
{ 直到 I 走到整个数组的最后,表示再没有元素需要被移动 }
until I >= R;
{ 此时,整个指针数组排序完毕 }
end;

个人能力有限,理解难免有偏差,如果有更好的解释,欢迎批评指正!
.

.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  delphi integer function div