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

【Delphi】对 QuickSort 函数的理解分类

2012-09-14 00:43 183 查看
【Delphi】对 QuickSort 函数的理解分类: 【Delphi XE】组件学习笔记 2012-01-01 16:14 233人阅读 评论(0) 收藏 举报在 Delphi 的 Classes 单元定义了 TList 类,TList 有一个 Sort 方法,用来对 TList 里面的指针数组进行排序,这个方法调用了 QuickSort 函数,这个函数不好理解,我看了很久才看明白。记录下来,以免将来忘记了。[delphi] view plaincopy { 对指针进行排序,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; 个人能力有限,理解难免有偏差,如果有更好的解释,欢迎批评指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: