{I wrote a small Program to bench both sort routines we posted. It was an interesting test, however it did raise a couple questions For me, which I'll get to in a moment. (The following Program can be used as a skeleton For trying other sort routines too.) Needless to say, the routine you posted was dramatically faster than the one I posted, even though both routines are non-recursive simple sorts. The maximum efficient load of the routine you posted appears to be about 3000 elements. After that, additonal elements add time exponentially. For example, it will sort 3000 elements in 5.1 seconds, but 5000 elements takes almost 16 seconds. The sort I posted became un-benchable [bearable] at about 3000 elements when it took over a minute to Complete. I didn't test it beyond this point. Here are the results from my 386 33Mhz machine-- your algorithm. 500 Elements - 0.1 Seconds 1000 Elements - 0.8 Seconds 1500 Elements - 1.4 Seconds 2000 Elements - 2.6 Seconds 3000 Elements - 5.1 Seconds <- Peak efficiency reached 5000 Elements - 15.8 Seconds Here is the Program I used to benchmark with. I made it so that you could "tweak" portions of the sort and re-run the Program. Incidentally, I also Compiled this Program under Stony Brook's Pascal Plus and was suprised to find that it ran substantially slower. All optimizations on. Range Checking ($R+) exactly Doubled the time it took to sort. Changing "Span+1" to Succ(Span) and "total-1" to Pred(total) made the routine about 3% faster. However the routine then neglected to sort that last two elements. Adding "Inc(total,2)" solved the problem but I'm not sure why. I did not expect this behavior. Perhaps someone could explain why? I added a temporary Pointer Variable to your routine in place of the "NewStr(' ... ')" code you used to simplify it. and one last thing... Using OPRO's OpInline Function called "ExchangeLongInts()" to do the swapping instead of using a temporary Var increased speed another 2% (Evident at > 2000 elements.) However I did not include this so that anyone interested could Compile and run this without extra Units. } {$A+,B-,D-,E-,F-,G-,I+,L+,N-,O-,P-,Q+,R-,S+,T-,V-,X-,Y+} {$M 32768,0,655360} Program Sort_Test; { Sorting Benchmark Using P. Beeftink's Algorithm } Type SmallArrPtr = ^SmallArr; SmallArr = Array[1..10] of Char; { Skip String & Length Byte } TTimeString = String[20]; Var SortArray : Array[1..5000] of SmallArrPtr; { A LARGE Array } TickCount : LongInt Absolute $0040:$006C; { TickCount : LongInt VOLATILE Absolute $0040:$006C; } { For Pascal+ } Tstart, Ttime : LongInt; {------------------------------------------------------------------------} Procedure StartTiming; begin TStart := TickCount; {start at the beginning of a tick!} Repeat Until TStart <> TickCount; TStart := TickCount; end; {------------------------------------------------------------------------} Procedure StopTiming; begin TTime := TickCount - TStart; end; {------------------------------------------------------------------------} Function Elapsed : TTimeString; Var Temp : TTimeString; Sec10 : LongInt; begin Sec10 := TTime * 2470 div 4497; Str( Sec10 : 4, Temp ); if Temp[1] = ' ' then Temp[1] := '0'; Inc( Temp[0] ); Temp[ Length(Temp) ] := Temp[ Pred( Length( Temp ) ) ]; Temp[ Pred( length( Temp ) ) ] := '.'; Elapsed := Temp; end; {------------------------------------------------------------------------} Procedure MakeRandomStrings( NumtoMake : Word ); Var RNum, I,S : Word; Temp : String; begin Temp := ''; Temp[0] := Chr( 10 ); Randomize; For I := 1 to NumtoMake do begin For S := 1 to 10 do { Create Random Strings 10 Chars in length } begin RNum := Random(26); Temp[S] := Chr( RNum + 65 ); end; Move( Temp[1], SortArray[I]^, 10 ); end; end; { Proc } {------------------------------------------------------------------------} Procedure KDSort( total : Word ); {-My simple sort routine as posted in Pascal Echo } { With 2 slight modifications } Var i,j, Current : Word; TempPtr : Pointer; begin For I := 1 to total do begin Current := I; For J := Succ(I) to total do begin if SortArray[J]^ < SortArray[Current]^ then begin TempPtr := SortArray[j]; SortArray[j] := SortArray[Current]; SortArray[Current] := TempPtr; end; {if} end; {For} end; {For} end; {------------------------------------------------------------------------} Procedure PBSort(total : Integer); {-Peter Beeftink's Sort as Posted in Pascal Echo } { Also With slight modifications } Var I,j : Integer; Span : Integer; TempPtr : Pointer; begin Inc(total,2); { Required to Compensate For PRED and SUCC ? } Span := total SHR $01; While Span > 0 do begin For I := Span to Pred(total) {total-1} do begin For j := (I - Succ(Span) {Span+1} ) Downto 1 do if (SortArray[j]^ <= SortArray[j+Span]^) then j := 1 else begin TempPtr := SortArray[j]; SortArray[j] := SortArray[j+Span]; SortArray[j+Span] := TempPtr; end; end; {For} Span := Span SHR $01; { This does help speed over Span div 2! } end; {WhIle} end; {------------------------------------------------------------------------} Procedure Do_Sorting( SortAmount : Word ); begin MakeRandomStrings(SortAmount); Write('Sorting... '); StartTiming; PBSort(SortAmount); { Change to KDSort() to bench second sort routine } StopTiming; WriteLn(SortAmount:5,' Elements - ',Elapsed,' Seconds'); end; {------------------------------------------------------------------------} Var C : Word; begin if MaxAvail < 5000 * Sizeof(SmallArr) then Halt; { not enough memory! } For C := 1 to 5000 do { pre-allocate up front } GetMem(SortArray[C],Sizeof(SmallArr)); Do_Sorting( 500 ); { Add more Do_Sorting()'s For whatever count } Do_Sorting( 1000 ); { you wish to test with. } Do_Sorting( 1500 ); Do_Sorting( 2000 ); Do_Sorting( 3000 ); Do_Sorting( 5000 ); { Un-comment the following if you wish to see the sorted output } { For C := 1 to 5000 do { Change 5000 to the amount you sorted } WriteLn( SortArray[C]^ ); For C := 1 to 5000 do FreeMem(SortArray[C],Sizeof(SmallArr)); end. { I plugged in a QuickSort algorithm in the "skeleton" Program in my previous message to test perFormance. Here are the results: 500 Elements - 0.1 Seconds 1000 Elements - 0.2 Seconds 1500 Elements - 0.4 Seconds 2000 Elements - 0.6 Seconds 3000 Elements - 0.9 Seconds 5000 Elements - 1.8 Seconds Very fast indeed. I modified the algorithm to sort only by Pointers, and optimized a couple spots. Again, a slight speed increase is noted using OPRO's ExchangeLongInts() in leu of using temporary Variables in 1 spot. if you have OPRO, replace them and you reduce the number of instructions by 2 per iteration. This is a split-list recursive sort. Works by making a pass through the entire Array first and moves all "small" data to the left, and all "Large" data to the right. then it sorts each half seperately. Take the following code segment and "plug" it into the skeleton in my previous message. then change the "PBSort(SortAmount)" to "QuickSort(SortAmount)" to run the tests. Here is the code segment: {------------------------------------------------------------------------} Procedure QuickSort( total : Integer ); {------------------------------------------} Procedure recQuickSort( L, R : Integer ); Var K,I,J : Integer; T, Temp : Pointer; begin if L < R then begin T := SortArray[L]; I := Pred(L); J := L; K := Succ(R); While Succ(J) < K do if SortArray[Succ(J)]^ < SmallArrPtr(T)^ then begin Inc(I,1); Inc(J,1); SortArray[I] := SortArray[J]; SortArray[j] := T; end {if} else if SortArray[Succ(J)]^ > SmallArrPtr(T)^ then begin Dec(K,1); Temp := SortArray[K]; SortArray[K] := SortArray[Succ(J)]; SortArray[Succ(J)] := Temp; end {if} else Inc(J,1); recQuickSort(L,I); recQuickSort(K,R); end; { if L < R } end; { Proc recQuickSort } {------------------------------------------} begin recQuickSort(1,total); end;{QuickSort} {------------------------------------------------------------------------}