Einzelnen Beitrag anzeigen

Andreas13

Registriert seit: 14. Okt 2006
Ort: Nürnberg
451 Beiträge
 
Delphi XE5 Professional
 
#13

AW: Sortieren eines Arrays of String

  Alt 8. Jul 2019, 16:53
Hallo,
wenn es jetzt schon um die Sortiergeschwindigkeit geht (wir reden hierbei nicht unbedingt nur über die zu sortierenden 98 Datensätzen), dann möchte ich auch meinen „Senf“ dazu geben und einen vollkommen anderen Ansatz zeigen. Zunächst möchte jedoch auch ich feststellen, daß
a):
die Lösung von Der schöne Günther sehr professionell & komplex ist und viel Know-how enthält und voraussetzt.
b):
die Lösung von Delphi.Narium sehr kompakt, verständlich und elegant ist und sortiert direkt im Memo.

Mein Ansatz sieht wie folgt aus: Da DonPedroFo die „Adressen“ bereits aus seinen Stringzeilen extrahiert hat, könnte er (wenn er Zeit & Lust zum Experimentieren hat) folgendes machen:
1):
Die extrahierten „Adressen“ in einen IntegerVektor (= Array of Integer) packen,
2):
Die kompletten Original-Strings (unverändert) in einen StringVektor (= Array of String) laden.

Ich habe vor längerer Zeit eine Routine zum MIT-Sortieren von gekoppelten Extended- und Integer-Vektoren (= Arrays) entwickelt, dessen Code unten folgt. Der MasterVektor wird hierbei sortiert, der Rest (in der Routine 3 weitere Vektoren) erfährt aber dieselben Tauschaktionen, wird also quasi mitsortiert.
In DonPedroFo's Fall wäre der zu sortietrende IntegerVektor der MasterVektor. Der StringVektor wird ohne Vergleichsoperationen nur "mitbewegt". Mit geringem Aufwand lässt sich meine Routine anpassen. Gegebenenfalls kann man die überflüssigen Vektoren löschen oder einfach den NILVektor-DummyParameter übergeben.
Delphi-Quellcode:
Type
  TDynExtendedVektor = TArray<Extended>; // = Array of Extended;
  TDynIntegerVektor = TArray<Integer>; // Array of Integer;


(* Krücken: sie sollten eigentlich CONSTANT sein: es geht aber NICHT! *)
VAR
  NILVektor_Extended: TDynExtendedVektor;
  NILVektor_Integer : TDynIntegerVektor;
 (* Eigentlich Krücken: sie sollten eigentlich CONSTANT sein: es geht aber NICHT!
  Solange Länge NICHT gesetzt wird, ist es ein NIL-Vektor bzw. eine NIL-Matrix *)




Procedure MIT_Sort_Extended_Vektor_byQuick(VAR A_Vektor_MASTER: TDynExtendedVektor;
                                                  VAR B_Vektor: TDynExtendedVektor;
                                                  VAR C_Vektor: TDynExtendedVektor;
                                                  VAR I_Vektor: TDynIntegerVektor;
                                                   Aufsteigend: Boolean = True);

// Angepasst nach Easy Delphi Helper's QuickSort für Integer_Vektor; Rekursiv --> STACK!!
// Zum MIT_Sortieren zugehöriger Vektoren
// QuickSort ist ein rekursives (STACK!!!), instabliles (!!) Sortierverfahren,
// Problematisch ist, wenn zwei Einträge genau gleich sind
//
// beim Fehlen eines Vektors, als Parameter folgende Dummys übergeben:
// NILVektor_Extended: TDynExtendedVektor;
// NILVektor_Integer : TDynIntegerVektor;

  Procedure Quick_Sort(Var a: TDynExtendedVektor; VAR b: TDynExtendedVektor;
                       VAR c: TDynExtendedVektor; VAR iV: TDynIntegerVektor; iLo, iHi: Integer);

  var
    Lo, Hi : Integer;
    Mid, T : Extended;
    T_B, T_C: Extended;
    T_i : Integer;

  Begin
    Lo := iLo;
    Hi := iHi;
    Mid:= a[(Lo + Hi) div 2];
    Repeat
      While a[Lo] < Mid Do
        Inc(Lo);

      While a[Hi] > Mid Do
        dec(Hi);

      IF Lo <= Hi Then Begin // ALLE Vertauschungen sind HIER:
        // A:
        T := a[Lo];
        a[Lo]:= a[Hi];
        a[Hi]:= T;

        // B:
        IF b <> NIL Then Begin
          // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
          T_B := b[Lo];
          b[Lo]:= b[Hi];
          b[Hi]:= T_B;
        End;

        // C:
        IF c <> NIL Then Begin
          // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
          T_C := c[Lo];
          c[Lo]:= c[Hi];
          c[Hi]:= T_C;
        End;

        // iV:
        IF iV <> NIL Then Begin
          // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
          T_i := iV[Lo];
          iV[Lo]:= iV[Hi];
          iV[Hi]:= T_i;
        End;

        Inc(Lo);
        dec(Hi);
      End;
    Until Lo > Hi;

    IF Hi > iLo Then
      Quick_Sort(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor, iLo, Hi);

    IF Lo < iHi Then
      Quick_Sort(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor, Lo, iHi);
  End;

Begin
  // Rekursiver Aufruf:
  Quick_Sort(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor, Low(A_Vektor_MASTER), High(A_Vektor_MASTER));

  IF Aufsteigend Then
    Exit;

  // Absteigend: -> Krücke: Umkopieren!
  Vektor_Umsortieren(A_Vektor_MASTER, B_Vektor, C_Vektor, I_Vektor);
End;{MIT_Sort_Extended_Vektor_byQuick}
{------------------------------------}

Procedure Vektor_Umsortieren(VAR A_Vektor: TDynExtendedVektor;
                             VAR B_Vektor: TDynExtendedVektor;
                             VAR C_Vektor: TDynExtendedVektor;
                             VAR I_Vektor: TDynIntegerVektor); overload;

// Dreht die Sortierfolge durch Umkopieren um: Aufsteigend --> Absteigend bzw. Absteigend --> Aufsteigend
// ist nur eine Krücke, Doch der Aufwand, direkt Absteigend zu sortieren ist viel größer...
// beim Fehlen eines Vektors, als Parameter folgrnde Dummys übergeben:
// NILVektor_Extended: TDynExtendedVektor;
// NILVektor_Integer : TDynIntegerVektor;

VAR
  i, j, tmp_i : Integer;
  tmp_A, tmp_B, tmp_C: Extended;

Begin
  j:= High(A_Vektor);

Begin
  For i:= Low(A_Vektor) To (High(A_Vektor) div 2) Do Begin
    // A:
    tmp_A := A_Vektor[i];
    A_Vektor[i]:= A_Vektor[j];
    A_Vektor[j]:= tmp_A;

    // B:
    IF B_Vektor <> NIL Then Begin
      // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
      tmp_B := B_Vektor[i];
      B_Vektor[i]:= B_Vektor[j];
      B_Vektor[j]:= tmp_B;
    End;

    // C:
    IF C_Vektor <> NIL Then Begin
      // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
      tmp_C := C_Vektor[i];
      C_Vektor[i]:= C_Vektor[j];
      C_Vektor[j]:= tmp_C;
    End;

    // Integer:
    IF I_Vektor <> NIL Then Begin
      // NIL lässt sich NICHT DIREKT als Paramter für den Vektor übergeben, nur über einen Dummy-Vektor: NILVektor_Extended oder NILVektor_Integer
      tmp_i := I_Vektor[i];
      I_Vektor[i]:= I_Vektor[j];
      I_Vektor[j]:= tmp_i;
    End;

    dec(j);
  End;
End;{Vektor_Umsortieren}
{----------------------}
Vielleicht hilft es jemandem in ähnlichen Aufgabenstellungen weiter.
Gruß
Andreas
Wenn man seinem Nächsten einen steilen Berg hinaufhilft, kommt man selbst dem Gipfel näher.
John C. Cornelius

Geändert von Andreas13 ( 8. Jul 2019 um 17:05 Uhr)
  Mit Zitat antworten Zitat