![]() |
Sortierung unwirksam
Hi,
Ich hab eine Liste abgeleitet von TList mit Items die je zwei Integerwerte enthalten. Ich hab mal was vereinfachtes nachprogrammiert. Angenommen wir haben eine TPointList mit Items vom Typ PPoint. Jetzt will ich diese Liste nach den y-Werten der Punkte sortieren. Dazu benutze ich Quicksort. Hier erstmal der Quelltext:
Delphi-Quellcode:
Implementation der Liste:
interface
type PPoint = ^TPoint; TPointList = class(TList) private function GetItem(Index: Integer): PPoint; procedure SetItem(Index: Integer; const Value: PPoint) public function Add(APoint: PPoint): Integer; property Items[Index: Integer]: PPoint read GetItem write SetItem; default; end;
Delphi-Quellcode:
Eigentlicher Quellcode:
{ TPointList }
function TPointList.Add(APoint: PPoint): Integer; begin Result := inherited Add(APoint); end; function TPointList.GetItem(Index: Integer): PPoint; begin Result := PPoint(inherited Items[Index]); end; procedure TPointList.SetItem(Index: Integer; const Value: PPoint); begin inherited Items[Index] := Value; end;
Delphi-Quellcode:
Dummerweise stehn in beiden Listboxen das gleiche. Die Liste wird einfach nicht sortiert. Habe mal mit Breakpoints in der Quicksort procedure geguckt und da wird alles Ordnungsgemäß ausgetauscht. Ach ja: Es ist wichtig das die Pointer ausgetauscht werden und nicht nur die Werte selbst!
var list: TPointList;
procedure TForm1.FormCreate(Sender: TObject); var i: Integer; tmp: PPoint; begin List := TPointList.Create; for i := 1 to 30 do // Liste mit zufälligen Punkten füllen begin New(tmp); tmp^.X := random(256); tmp^.Y := random(256); List.Add(tmp); end; end; procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin // Unsortiert anzeigen for i:=0 to List.Count-1 do Listbox1.Items.Add('(' + IntToStr(List[i]^.X) + '|' + IntToStr(List[i]^.Y) + ')'); // Sortieren SortList(list,0,List.Count-1); // Sortiert anzeigen for I := 0 to List.Count - 1 do Listbox2.Items.Add('(' + IntToStr(List[i]^.X) + '|' + IntToStr(List[i]^.Y) + ')'); end; // Quicksort procedure SortList(var AList: TPointlist; l,r: Integer); function Divide(s,t: Integer): Integer; var i,j: Integer; pivot: Integer; tmp: PPoint; begin i := s-1; j := t+1; pivot := AList[t]^.Y; repeat repeat inc(i) until AList[i]^.Y >= pivot; repeat dec(j); until AList[j]^.y <= pivot; tmp := AList[i]; AList[i] := AList[j]; AList[j] := tmp; until i <= j; tmp := AList[i]; AList[i] := AList[j]; AList[j] := tmp; Result := i; end; var m: Integer; begin if l < r then begin m := Divide(l,r); SortList(AList,l,m-1); SortList(AList,m+1,r); end; end; Ich versteh jetzt nicht was da schief läuft... Gruß Neutral General |
Re: Sortierung unwirksam
Soweit ich weiss, geht das einfacher.
Zitat:
Zitat:
Zitat:
|
Re: Sortierung unwirksam
Ja theoretisch schon aber das Problem ist:
Ich will selbst sortieren. Vorallem weil wie gesagt nicht die Werte vertauscht werden sollen sondern die Pointer. Das ist wichtig! |
Re: Sortierung unwirksam
Zitat:
Es arbeitet ja auch mit Pointern. Und TList-intern wird dann ja erst sortiert. |
Re: Sortierung unwirksam
Ehm ich hab jetzt nochmal ein Quicksort geschrieben. Also ich glaube langsam da will mich was verarschen...
Hier nochmal als Beispiel: Ein Array of TList (bzw ein Nachfahre davon). Ich will das Array nach der Anzahl der Elemente in den Listen sortieren.
Delphi-Quellcode:
Da wird wieder nichts sortiert. Ich werd langsam verrückt -.-
type
TCombis = Array of Tlist; procedure SortArray(var CombiArray: TCombis; l,r: Integer); function Divide(l,r: Integer): Integer; procedure Exchange(s,t: Integer); var tmp: TList; begin tmp := CombiArray[s]; CombiArray[s] := CombiArray[t]; CombiArray[t] := tmp; end; var i,j: Integer; pivot: Integer; begin i := l-1; j := r+1; pivot := CombiArray[r].Count; repeat repeat inc(i); until CombiArray[i].Count >= pivot; repeat dec(j); until CombiArray[j].Count <= pivot; Exchange(i,j); until i <= j; Exchange(i,j); Result := i; end; var m: Integer; begin if r > l then begin m := Divide(l,r); SortArray(CombiArray,l,m-1); SortArray(CombiArray,m+1,r); end; end; Gruß Neutral General |
Re: Sortierung unwirksam
Hi,
Ich wollte das Thema nochmal aufgreifen.. *push* Es wär nett wenn sich das jemand angucken könnte.. |
Re: Sortierung unwirksam
du solltest nicht eine komponente, selbst versuchen zu sortieren, da bringste nur alles durcheinander.. verwende dafür die methode sort, deiner klasse.
wenn du selbst sortieren willst, dann erstell dir deine eigene komponente/object, wo du den speicher selbst verwaltest... da kanntste dann den qSort aus TList nachprogrammieren :roll: :roteyes: :roteyes: |
Re: Sortierung unwirksam
Zitat:
|
Re: Sortierung unwirksam
Hallo Michael,
welchen Algorithmus implementierst du da? Ich habe mal ![]()
Delphi-Quellcode:
Funktioniert. Vielleicht findest du deinen Fehler durch Vergleich - oder du schreibst dir eine Visualisierung.
function Compare(item1, item2: TList): Integer;
begin Result := Math.CompareValue(item1.Count, item2.Count); end; procedure Exchange(var a: TCombis; index1, index2: Integer); var tmp: TList; begin tmp := a[index1]; a[index1] := a[index2]; a[index2] := tmp; end; procedure QuickSort(var a: TCombis; iLow, iHigh: Integer); var iL, iH: Integer; pivot: TList; begin iL := iLow; iH := iHigh; pivot := a[(iLow + iHigh) shr 1]; while iL <= iH do begin while Compare(a[iL], pivot) < 0 do Inc(iL); while Compare(a[iH], pivot) > 0 do Dec(iH); if iL <= iH then begin Exchange(a, iL, iH); Inc(iL); Dec(iH); end; end; if iLow < iH then QuickSort(a, iLow, iH); if iL < iHigh then QuickSort(a, iL, iHigh); end; Grüße vom marabu |
Re: Sortierung unwirksam
Hi,
Hab mich ![]() Gruß Neutral General |
Re: Sortierung unwirksam
Hi,
Zitat:
Delphi-Quellcode:
Du hast dich offensichtlich von der visuellen Ähnlichkeit des Pseudo-Codes "wiederhole block solange bedingung" mit einer REPEAT-Schleife täuschen lassen. Tatsächlich ist es aber eine WHILE-Schleife.
procedure SortArray(var CombiArray: TCombis; l, r: Integer);
function Divide(l, r: Integer): Integer; procedure Exchange(s,t: Integer); var tmp: TList; begin tmp := CombiArray[s]; CombiArray[s] := CombiArray[t]; CombiArray[t] := tmp; end; var pivot: Integer; begin // Dec(l); // muss wech! pivot := r; while l < r do begin while CombiArray[l].Count < CombiArray[pivot].Count do Inc(l); while (l < r) and (CombiArray[r].Count > CombiArray[pivot].Count) do Dec(r); if l < r then Exchange(l, r); end; Exchange(l, pivot); Result := l; end; Freundliche Grüße |
Re: Sortierung unwirksam
Hi,
Danke. Aber das Problem ist: Das funktioniert auch nicht. Bekomme in der Zeile
Delphi-Quellcode:
irgendwann ne AV. Ist eigentlich auch logisch bei ner while schleife weil da erst geprüft wird und dann ausgeführt.. d.h. man fängt mit CombiArray[-1] an, wohingegen man bei repeat bei 0 anfängt weil vorher geinct wird. Wenn ich das dec weglasse hab ich ne Endlosschleife.
while CombiArray[l].Count < CombiArray[Pivot].Count do
Naja hab das gefunden was unser Info-Lehrer uns gegeben hat: ![]() da wirds auch mit repeat gemacht und mit <= und >= ... Mein Quelltext sieht jetzt so aus:
Delphi-Quellcode:
Gruß
procedure SortArray(var CombiArray: TCombis; l,r: Integer);
function Divide(l,r: Integer): Integer; procedure Exchange(s,t: Integer); var tmp: TPriceList; begin tmp := CombiArray[s]; CombiArray[s] := CombiArray[t]; CombiArray[t] := tmp; end; var pivot: Integer; k: Integer; begin dec(l); pivot := r; while l < r do begin while CombiArray[l].Count < CombiArray[Pivot].Count do inc(l); while (l < r) and (CombiArray[r].Count > CombiArray[Pivot].Count) do dec(r); if l < r then Exchange(l,r); { Form1.ListBox1.Clear; for k := 0 to High(CombiArray) do begin Form1.ListBox1.Items.Add(IntToStr(CombiArray[k].Count)); Application.ProcessMessages; end; sleep(10); } end; Exchange(l,pivot); Result := l; end; var m: Integer; begin if r > l then begin m := Divide(l,r); SortArray(CombiArray,l,m-1); SortArray(CombiArray,m+1,r); end; end; Neutral General |
Re: Sortierung unwirksam
Hi,
bei meinen drei Tests ist zwar der Fehler nicht aufgetreten, aber du hast Recht: Der Lower Bound Index darf beim Start von SortArray() nicht verringert werden. Ob du nun REPEAT oder WHILE verwendest, dass ist gehoppt wie gesprungen, wenn du die Abbruchbedingungen und die Initialwerte richtig angepasst hast. Insofern ist der Wikipedia Pseudo-Code sowas wie "REPEAT Block WHILE Bedingung". Freundliche Grüße |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:52 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz