Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Generics.TObjectList Items vertauschen (https://www.delphipraxis.net/172832-generics-tobjectlist-items-vertauschen.html)

HJay 24. Jan 2013 17:02

Generics.TObjectList Items vertauschen
 
Ich möchte übungshalber eigene Sortierroutinen schreiben und Generics üben.

Nun habe ich versucht, Quicksort (kopiert von classes.pas) zum Laufen zu bringen, aber offensichtlich (?) darf man nicht zwei Elemente mit Items[i] := Items[j] vertauschen -- zumindest erhalte ich sofort einen EInvalidPointer ("ungültige Zeigeroperation) mit Absturz, wenn ich es ausführe.

Wie vertauscht man denn zwei Items miteinander? Was mache ich falsch?

(PS: Im Vergleich zu meiner zweiten Frage bzgl. URW1111 ist hier alles identisch, nur in EINER Unit zusammengezogen.)

Code:
unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Generics.Collections;

type
  TSortObjectList<T: class> = class(TObjectList<T>)
    type TCompareItems<T> = function(AItem, BItem: T): Integer of Object;
    procedure QuickSort(Left, Right: Integer; ACompareMethod: TCompareItems<T>); overload;
  end;

  TMyItem = class(TObject)
    Dummy: String;
  end;

  TTestList = class(TSortObjectList<TMyItem>)
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo; { enthält sieben Zeilen mit jeweils einem Buchstaben }
    procedure Button1Click(Sender: TObject);
  private
    function CompareTest(AItem, BItem: TMyItem): Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TSortObjectList<T>.QuickSort(Left, Right: Integer; ACompareMethod: TCompareItems<T>);
  var I, J: Integer;
      Pivot, Temp: T;
begin { QuickSort procedure from Classes.pas. }
  repeat
    I := Left;
    J := Right;
    Pivot := Items[(Left + Right) shr 1];
    repeat
      while ACompareMethod(Items[I], Pivot) < 0 do Inc(I);
      while ACompareMethod(Items[J], Pivot) > 0 do Dec(J);
      if I <= J then begin
        Temp := Items[I];
        Items[I] := Items[J];
        Items[J] := Temp;
        Inc(I);
        Dec(J);
      end;
    until I > J;
    if Left < J then QuickSort(Left, J, ACompareMethod);
    Left := I;
  until I >= Right;
end;

procedure TForm1.Button1Click(Sender: TObject);
var A : TTestList;
      j : Integer;

  function MakeTestItem(AString: String): TMyItem;
  begin Result := TMyItem.Create; Result.Dummy := AString; end;

begin
  A := TTestList.Create(True);
  for j := 0 to Pred(Memo1.Lines.Count) do A.Add(MakeTestItem(Memo1.Lines[j]));

  A.QuickSort(0, Pred(A.Count), CompareTest);

  Memo1.Clear;
  for j := 0 to Pred(A.Count) do Memo1.Lines.Add(A[j].Dummy);

  A.Free;
end;

function TForm1.CompareTest(AItem, BItem: TMyItem): Integer;
begin
  Result := CompareStr(AItem.Dummy, BItem.Dummy);
end;

end.

HJay 24. Jan 2013 17:45

AW: Generics.TObjectList Items vertauschen
 
Ah ja, ich habe selbst die Funktion Exchange() entdeckt, frage mich aber rein interessehaber dennoch, warum man nicht dierekt die Items einander zuweisen kann. Was ist falsch mit diesem Vorgehen?

daywalker9 24. Jan 2013 18:21

AW: Generics.TObjectList Items vertauschen
 
Das liegt an dem OwnsObjects der TObjectList, sobald das true ist und du die Items so zuweist, wird das bestehende Item freigegeben. Die Delphi interne Implementierung in System.Generics.Collections.pas TArray<T>.QuickSort arbeitet direkt mit dem Array of T von der TObjectList und nicht mit der TObjectList selber.

HJay 24. Jan 2013 18:38

AW: Generics.TObjectList Items vertauschen
 
Super Antwort, verständlich und logisch. Danke!

Exchange() hat das Problem zum Glück inhaltlich gelöst, aber nun ist auch klar, warum es nicht ging.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz