如何在Delphi中实现快速排序而不会因大量记录而出现Access违规错误?

时间:2014-02-11 10:48:06

标签: delphi quicksort

这是我目前的代码:

function StudentQuickSort(StudentList:TStudentArray;ArrayLength:integer):TStudentArray;
var
  Pivot:TstudentArray;
  LesserList:TStudentArray;
  GreaterList:TstudentArray;
  ArrayCount:Integer;
  LesserCount:Integer;
  GreaterCOunt:integer;
procedure ConcatArrays(const A,B,C: TStudentArray; var D: TStudentArray);
  var i, nA,nB,nC: integer;
  begin
    nA := length(A);
    nB := length(B);
    nC := Length(C);
    SetLength(D,nA+nB+nC);
    for i := 0 to nA-1 do
      D[i] := A[i];
    for i := 0 to nB-1 do
      D[i+nA] := B[i];
    for i := 0 to nC-1 do
      D[i+nA+nB] := C[i];
  end;

begin
  if Arraylength<=1 then
    begin
      Result:=(StudentList);
    end
  else
    begin
      SetLength(StudentList,ArrayLength);
      SetLength(LesserList,ArrayLength);
      SetLength(GreaterList,ArrayLength);
      SetLength(Pivot,1);
      LesserCOunt:=0;
      GreaterCount:=0;
      Pivot[0]:=StudentList[0];
      for ArrayCount := 1 to ArrayLength-1 do
        begin
          if strtoint(StudentList[ArrayCount].StudentNo)>strtoint(Pivot[0].StudentNo) then
           begin
              GreaterList[GreaterCOunt]:=StudentList[ArrayCount];
              GreaterCount:=GreaterCount+1;
           end
         else
            begin
              LesserList[LesserCOunt]:=StudentList[ArrayCount];
              LesserCount:=LesserCount+1;
            end;
        end;
        SetLength(LesserLIst,LesserCount);
        SetLength(GreaterList,GreaterCount);
        ConcatArrays(StudentQuickSort(LesserList,LesserCount),Pivot,StudentQuickSort(GreaterList,GreaterCount),Result)
    end;
end;

如何稳定,理想情况下尽可能少地改变代码。这是使用动态数组的问题吗?我需要能够无错误地对至少600条记录进行排序。

1 个答案:

答案 0 :(得分:4)

您的代码无法挽救。您将以错误的方式解决此问题,我建议您放弃现有代码。以下是我认为应该进行排序的方法。

请注意,我假设您没有可用的泛型。在现代Delphi版本中,您可以使用TArray.Sort<T>中的Generics.Collections进行排序。如果您有权访问它,则应该使用它

首先,关键是将排序与正在排序的数组分开。要实现这一目标,请定义以下类型:

type
  TCompareIndicesFunction = function(Index1, Index2: Integer): Integer of object;
  TExchangeIndicesProcedure = procedure(Index1, Index2: Integer) of object;

关键是所有可以对数组进行排序的常用算法只需要能够比较两个项目,并交换两个项目。这些过程类型可以将排序算法与底层数组存储和类型分开。

有了这些定义,我们就可以编写通用的排序算法了。对于quicksort,它看起来像这样:

procedure QuickSort(Count: Integer; Compare: TCompareIndicesFunction; 
  Exchange: TExchangeIndicesProcedure);

  procedure Sort(L, R: Integer);
  var
    I, J, P: Integer;
  begin
    repeat
      I := L;
      J := R;
      P := (L+R) div 2;
      repeat
        while Compare(I, P)<0 do inc(I); 
        while Compare(J, P)>0 do dec(J); 
        if I<=J then 
        begin
          if I<>J then 
          begin
            Exchange(I, J);
            //may have moved the pivot so we must remember which element it is
            if P=I then
              P := J
            else if P=J then
              P := I;
          end;
          inc(I);
          dec(J);
        end;
      until I>J;
      if L<J then 
        Sort(L, J); 
      L := I;
    until I>=R;
  end;

begin
  if Count>0 then
    Sort(0, Count-1);
end;

为了使用它,你需要将数组包装在一个暴露比较和交换方法的类中。