Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#62

Re: Große Datei sortieren ohne komplett in den Speicher zu l

  Alt 18. Mär 2009, 19:38
Satty67 und Himitsu: Die AnsiCompareStr / AnsiCompareText Funktionen sind ja unglaublich langsam. Ich habe mir erlaubt, dies etwas zu optimieren. Die Grundidee ist die, anhand der AnsiCompareXXX-Routinen eine 'SortOrder'-Tabelle für einzelne Zeichen zu erzeugen und die Strings Zeichen für Zeichen mit Hilfe dieser Tabelle zu vergleichen.

Dazu erstelle ich ein Array Of Char, mit A[c] = c. Danach sortiere ich dieses Array mit Hilfe der Ordnungsfunktion 'AnsiCompareStr'. Der Index des Zeichens 'C' ist also seine Ordnung. Wenn Index[C] > Index [D] (C und D sind Zeichen), dann liegt C in der Sortierreihenfolge hinter D. Logisch, irgendwie.

Nun nehme ich mir diese Indexfunktion und vergleiche mit ihrer Hilfe zwei Strings Zeichen für Zeichen. Ich vergleiche also nicht die Zeichen direkt, sondern ihren Index.

Hier die Routinen:
Delphi-Quellcode:
Var
  SortOrder : Array [Char] Of Integer;

Procedure CreateSortOrder;
var
  Samples: array[Char] of String;
  c, d, h: Char;

begin
  for c := #0 to #255 do
    Samples[c] := c;

// Bubblesort the array
  for c := #0 to #255 do
    for d := succ(c) to #255 do
      if AnsicompareStr(Samples[c], Samples[d]) > 0 then begin
        h := Samples[c];
        Samples[c] := Samples[d];
        Samples[d] := h
      end;

// Create the 'Index'-function
  for c := #0 to #255 do
    SortOrder[Samples[c]] := Ord(c);
end;
Und nun die Vergleichsfunktion
Delphi-Quellcode:
function FasterAnsiCompareString(const aKey1, aKey2: string): Integer;
Var
  P1,p2 : PChar;

Begin
  p1 := @aKey1[1];
  p2 := @aKey2[1];

  While (SortOrder[p1^] = SortOrder[p2^]) and (p1^<>#0) and (p2^<>#0) do Begin
     inc(p1);
     inc(p2);
  End;
  if SortOrder[p1^] = SortOrder[p2^] then
    Result := 0
  else if p1^ = #0 then
    Result := -1
  else if p2^ = #0 then
    Result := 1
  else Result := SortOrder[p1^]-SortOrder[p2^];
end;
Ich habe es ein wenig getestet, aber bitte prüft nochmal. Es ist 'etwas' schneller als AnsiCompareStr (bei mir: 43x )

Das, und eine robustere Version der Skiplists sollte die Disqualifikation aufheben. Auf meinem Laptop wird die Testdatei in 2300ms so sortiert, wie Satty67 es wünscht.
Angehängte Dateien
Dateityp: rar textsorter_710.rar (4,0 KB, 14x aufgerufen)
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat