瀏覽代碼

+ keep track of the pivot index in all quicksort implementations. No functional changes,
but will be used to prevent overlap in the divided subregions and also infinite loops
in case of an incorrect compare function.

git-svn-id: trunk@41222 -

nickysn 6 年之前
父節點
當前提交
26486bbaea
共有 1 個文件被更改,包括 41 次插入16 次删除
  1. 41 16
      rtl/inc/sortbase.pp

+ 41 - 16
rtl/inc/sortbase.pp

@@ -67,13 +67,14 @@ implementation
 Procedure QuickSort_PtrList_NoContext(ItemPtrs: PPointer; L, R : Longint;
                                       Comparer: TListSortComparer_NoContext);
 var
-  I, J : Longint;
+  I, J, PivotIdx : Longint;
   P, Q : Pointer;
 begin
  repeat
    I := L;
    J := R;
-   P := ItemPtrs[ (L + R) div 2 ];
+   PivotIdx := (L + R) div 2;
+   P := ItemPtrs[PivotIdx];
    repeat
      while Comparer(P, ItemPtrs[i]) > 0 do
        Inc(I);
@@ -84,6 +85,10 @@ begin
        Q := ItemPtrs[I];
        ItemPtrs[I] := ItemPtrs[J];
        ItemPtrs[J] := Q;
+       if PivotIdx = I then
+         PivotIdx := J
+       else if PivotIdx = J then
+         PivotIdx := I;
        Inc(I);
        Dec(J);
      end;
@@ -117,13 +122,14 @@ procedure QuickSort_PtrList_Context(ItemPtrs: PPointer; ItemCount: SizeUInt; Com
 
   procedure QuickSort(L, R : Longint);
   var
-    I, J : Longint;
+    I, J, PivotIdx : Longint;
     P, Q : Pointer;
   begin
     repeat
       I := L;
       J := R;
-      P := ItemPtrs[ (L + R) div 2 ];
+      PivotIdx := (L + R) div 2;
+      P := ItemPtrs[PivotIdx];
       repeat
         while Comparer(P, ItemPtrs[I], Context) > 0 do
           Inc(I);
@@ -134,6 +140,11 @@ procedure QuickSort_PtrList_Context(ItemPtrs: PPointer; ItemCount: SizeUInt; Com
           Q := ItemPtrs[I];
           ItemPtrs[I] := ItemPtrs[J];
           ItemPtrs[J] := Q;
+          if PivotIdx = I then
+            PivotIdx := J
+          else if PivotIdx = J then
+            PivotIdx := I;
+
           Inc(I);
           Dec(J);
         end;
@@ -169,13 +180,14 @@ var
 
   procedure QuickSort(L, R : Longint);
   var
-    I, J : Longint;
+    I, J, PivotIdx : Longint;
     P : Pointer;
   begin
     repeat
       I := L;
       J := R;
-      P := Items + ItemSize*((L + R) div 2);
+      PivotIdx := (L + R) div 2;
+      P := Items + ItemSize*PivotIdx;
       repeat
         while Comparer(P, Items + ItemSize*I, Context) > 0 do
           Inc(I);
@@ -188,10 +200,16 @@ var
             Move((Items + ItemSize*I)^, TempBuf^, ItemSize);
             Move((Items + ItemSize*J)^, (Items + ItemSize*I)^, ItemSize);
             Move(TempBuf^, (Items + ItemSize*J)^, ItemSize);
-            if P = (Items + ItemSize*I) then
-              P := Items + ItemSize*J
-            else if P = (Items + ItemSize*J) then
-              P := Items + ItemSize*I;
+            if PivotIdx = I then
+            begin
+              PivotIdx := J;
+              P := Items + ItemSize*PivotIdx
+            end
+            else if PivotIdx = J then
+            begin
+              PivotIdx := I;
+              P := Items + ItemSize*PivotIdx;
+            end;
           end;
           Inc(I);
           Dec(J);
@@ -232,13 +250,14 @@ procedure QuickSort_ItemList_CustomItemExchanger_Context(
 
   procedure QuickSort(L, R : Longint);
   var
-    I, J : Longint;
+    I, J, PivotIdx : Longint;
     P : Pointer;
   begin
     repeat
       I := L;
       J := R;
-      P := Items + ItemSize*((L + R) div 2);
+      PivotIdx := (L + R) div 2;
+      P := Items + ItemSize*PivotIdx;
       repeat
         while Comparer(P, Items + ItemSize*I, Context) > 0 do
           Inc(I);
@@ -249,10 +268,16 @@ procedure QuickSort_ItemList_CustomItemExchanger_Context(
           if I < J then
           begin
             Exchanger(Items + ItemSize*I, Items + ItemSize*J, Context);
-            if P = (Items + ItemSize*I) then
-              P := Items + ItemSize*J
-            else if P = (Items + ItemSize*J) then
-              P := Items + ItemSize*I;
+            if PivotIdx = I then
+            begin
+              PivotIdx := J;
+              P := Items + ItemSize*PivotIdx
+            end
+            else if PivotIdx = J then
+            begin
+              PivotIdx := I;
+              P := Items + ItemSize*PivotIdx;
+            end;
           end;
           Inc(I);
           Dec(J);