Autor Beitrag
Jerk
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 251

Vista Ultimate, Ubuntu
Turbo Delphi 2006
BeitragVerfasst: Mi 22.10.08 17:14 
Hallo allerseits, ich habe mir gedacht das ich aus spaß mal den Quicksort Algoprythmus optimiere, da ja die Standard Version mit while arbeitet und ich gehört hab das Rekursion schneller ist.

Also der Standard Quicksort:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
// Quelle http://www.stefan-baur.de/cs.algo.quicksort.html
procedure QuickSort(var A: array of Integer);

  procedure QSort(LoIndex, HiIndex: Integer);
  var
    Lo, Hi: Integer;
    Pivot: Integer;
    Swap: Integer;
  begin
    // Wähle stets das mittlere Element als Pivotelement.
    Pivot := A[(LoIndex + HiIndex) div 2];

    // Stelle die Ordnung bzgl. des Pivotelements her.
    Lo := LoIndex;
    Hi := HiIndex;
    repeat
      while A[Lo] < Pivot do Inc(Lo);
      while A[Hi] > Pivot do Dec(Hi)
;
      if Lo <= Hi then
      begin
        Swap := A[Lo];
        A[Lo] := A[Hi];
        A[Hi] := Swap;
        Inc(Lo);
        Dec(Hi);
      end;
    until Lo > Hi;

    // Gegebenenfalls linke Teilliste sortieren.
    if LoIndex < Hi then QSort(LoIndex, Hi);

    // Gegebenenfalls rechte Teilliste sortieren.
    if Lo < HiIndex then QSort(Lo, HiIndex);
  end;


Den Markierten Teil wollte ich wiegesagt durch Funktionen ersetzen die Rekursiv das gleiche machen.
Da dazu allerdings das Array übergeben werden muss, dachte ich löse ich das ganze mit Pointern.
Nur leider funktioniert das nicht:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
type
  TNums = Array[0..1000] of Integer;
  pArray = ^TNums;
  pPivot = ^Integer;

...

procedure TForm1.QuickSort(A: array of Integer; iLo, iHi: Integer) ;
var
  Lo, Hi, Pivot, T: Integer;
begin
  Lo := iLo;
  Hi := iHi;
  Pivot := A[(Lo + Hi) div 2];
  repeat
    Lo := SortLeft(@A,@Pivot,iLo);
    Hi := SortLeft(@A,@Pivot,iHi);

    if Lo <= Hi then
    begin
      T := A[Lo];
      A[Lo] := A[Hi];   
      A[Hi] := T;
      Inc(Lo) ;
      Dec(Hi) ;
    end;
  until Lo > Hi;
  if Hi > iLo then QuickSort(A, iLo, Hi) ;
  if Lo < iHi then QuickSort(A, Lo, iHi) ;
end;

Function TForm1.SortLeft(  ar : pArray;  Pivot :pPivot; Pos : Integer) : Integer;
var va,vb : Integer;
begin
  va := ar[Pos];
  vb := Pivot^;
 if va < vb then SortLeft(ar,Pivot,Pos+1)
 else
  Result:= Pos;
end;

Function TForm1.SortRight(ar : pArray; Pivot :pPivot; Pos : Integer) : Integer;
var va,vb : Integer;
begin
  va := ar[Pos];
  vb := Pivot^;
 if va > vb then SortLeft(ar,Pivot,Pos-1)
 else
  Result:= Pos;
end;


Ich bekomme leider immer nen Stack Overflow, nur wieso?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19346
Erhaltene Danke: 1754

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 22.10.08 20:38 
Ein Stackoverflow bedeutet meistens, dass irgendein rekursiver Aufruf nicht abgebrochen wird. (Oder etwas anderes den Stack gefüllt hat, aber Rekursionen sind meistens die Ursache.)

Ohne es mir jetzt ganz genau angeschaut zu haben würde ich beim Überfliegen sagen, dass er von SortLeft nach SortRight immer hin- und herspringt ohne abzubrechen oder ähnliches.

Debug das doch einfach und schau was passiert. Haltepunkt setzen und mit F7 bzw. F8 schrittweise durch gehen und die Werte deiner Variablen beobachten (ggf. mit markieren und Strg + F7 auswerten).
Jerk Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 251

Vista Ultimate, Ubuntu
Turbo Delphi 2006
BeitragVerfasst: Mi 22.10.08 20:58 
:autsch: Da hab ich mich so auf die Pointer fixiert und nen Simplen fehler übersehen, das der Funktionswert unbestimmt sein kann :oops:

Danke für die Hilfe.
Logikmensch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 390

Win XP
Delphi 2007 Prof., XE2, XE5
BeitragVerfasst: Do 23.10.08 09:48 
Ich hab auch gerade gesehen, dass der Funktionswert bei SortLeft nicht gesetzt wird.

Darüberhinaus frage ich mich, wozu die zusätzliche Rekursion? Die Lo-/Hi-Eingrenzung des zu sortierenden Bereiches gehört doch nur zum Verkleinern desselben. Die Routine arbeitet doch bereits rekursiv... Das SortLeft belastet m.E. nach nur den Stack, sonst nix.

_________________
Es gibt keine Probleme - nur Lösungen!