Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi problem beim sortieren einer verketteten liste (https://www.delphipraxis.net/138182-problem-beim-sortieren-einer-verketteten-liste.html)

arest 4. Aug 2009 22:39


problem beim sortieren einer verketteten liste
 
abend allerseits, hab nen problem mit meiner sortieren funktion für eine verkettete liste... hab eine liste, die über eingabefelder mit diverse daten gefüllt wird, welche ich nun über radiobuttons sortieren möchte. hab das sehr ähnlich bei einem anderen projekt schon mal gemacht und da hat es wunderbar funktioniert, jetzt streikt es allerdings :/ hier erst mal was vom code:

Delphi-Quellcode:
//********************************SORTIEREN FUNKTION*********************************
   //nachname
   procedure TForm1.RadioButton1Click(Sender: TObject);
   begin
      nachname:=true;
      vorname:=false;
      kategorie:=false;
      geburtstag:=false;
      sortieren;
   end;
   //vorname
   procedure TForm1.RadioButton2Click(Sender: TObject);
   begin
      nachname:=false;
      vorname:=true;
      kategorie:=false;
      geburtstag:=false;
      sortieren;
   end;
   //kategorie
   procedure TForm1.RadioButton5Click(Sender: TObject);
   begin
      nachname:=false;
      vorname:=false;
      kategorie:=true;
      geburtstag:=false;
      sortieren;
   end;
   //geburtstag
   procedure TForm1.RadioButton6Click(Sender: TObject);
   begin
      nachname:=false;
      vorname:=false;
      kategorie:=false;
      geburtstag:=true;
      sortieren;
   end;
   procedure TForm1.RadioButton3Click(Sender: TObject);
   begin
      sortieren;
   end;
   procedure TForm1.RadioButton4Click(Sender: TObject);
   begin
      sortieren;
   end;
   //sortieren
   procedure sortieren;
   begin
      lauf:=TKnoten.Init;
      if (anfang.nachfolger<>ende)
      then begin
              anfang2:=TKnoten.Init;
              ende2:=TKnoten.Init;
              anfang2.nachfolger:=ende2;
              ende2.vorgaenger:=anfang2;
              if (nachname=true)
              then begin
                      lauf:=anfang;
                      repeat lauf:=lauf.nachfolger;
                         neu2:=TKnoten.Init;
                         neu2.Daten:=lauf.Daten;
                         lauf2:=anfang2;
                         if (Form1.RadioButton3.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.nachname > neu2.Daten.nachname) or (lauf2=ende2);
                              end;
                         if (Form1.RadioButton4.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.nachname < neu2.Daten.nachname) or (lauf2=ende2);
                              end;
                         lauf2.vorgaenger.nachfolger:=neu2;
                         neu2.vorgaenger:=lauf2.vorgaenger;
                         lauf2.vorgaenger:=neu2;
                         neu2.nachfolger:=lauf2;
                      until (lauf=ende.vorgaenger);
                      anfang:=anfang2;
                      ende:=ende2;
                      knoteneinlesen;
                   end;
              if (vorname=true)
              then begin
                      lauf:=anfang;
                      repeat lauf:=lauf.nachfolger;
                         neu2:=TKnoten.Init;
                         neu2.Daten:=lauf.Daten;
                         lauf2:=anfang2;
                         if (Form1.RadioButton3.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.vorname > neu2.Daten.vorname) or (lauf2=ende2);
                              end;
                         if (Form1.RadioButton4.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.vorname < neu2.Daten.vorname) or (lauf2=ende2);
                              end;
                         lauf2.vorgaenger.nachfolger:=neu2;
                         neu2.vorgaenger:=lauf2.vorgaenger;
                         lauf2.vorgaenger:=neu2;
                         neu2.nachfolger:=lauf2;
                      until (lauf=ende.vorgaenger);
                      anfang:=anfang2;
                      ende:=ende2;
                      knoteneinlesen;
                   end;
              if (kategorie=true)
              then begin
                      lauf:=anfang;
                      repeat lauf:=lauf.nachfolger;
                         neu2:=TKnoten.Init;
                         neu2.Daten:=lauf.Daten;
                         lauf2:=anfang2;
                         if (Form1.RadioButton3.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.kategorie > neu2.Daten.kategorie) or (lauf2=ende2);
                              end;
                         if (Form1.RadioButton4.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.kategorie < neu2.Daten.kategorie) or (lauf2=ende2);
                              end;
                         lauf2.vorgaenger.nachfolger:=neu2;
                         neu2.vorgaenger:=lauf2.vorgaenger;
                         lauf2.vorgaenger:=neu2;
                         neu2.nachfolger:=lauf2;
                      until (lauf=ende.vorgaenger);
                      anfang:=anfang2;
                      ende:=ende2;
                      knoteneinlesen;
                   end;
              if (geburtstag=true)
              then begin
                      lauf:=anfang;
                      repeat lauf:=lauf.nachfolger;
                         neu2:=TKnoten.Init;
                         neu2.Daten:=lauf.Daten;
                         lauf2:=anfang2;
                         if (Form1.RadioButton3.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.geburtstag > neu2.Daten.geburtstag) or (lauf2=ende2);
                              end;
                         if (Form1.RadioButton4.Checked=true)
                         then begin
                                 repeat lauf2:=lauf2.nachfolger;
                                 until (lauf2.Daten.geburtstag < neu2.Daten.geburtstag) or (lauf2=ende2);
                              end;
                         lauf2.vorgaenger.nachfolger:=neu2;
                         neu2.vorgaenger:=lauf2.vorgaenger;
                         lauf2.vorgaenger:=neu2;
                         neu2.nachfolger:=lauf2;
                      until (lauf=ende.vorgaenger);
                      anfang:=anfang2;
                      ende:=ende2;
                      knoteneinlesen;
                   end;
      end;
   end;
das interessante ist, dass die sortierung auf nachname und vorname reagiert und soweit funktioniert, allerdings das auf/absteigend was über radiobutton3/4 abgefragt würde komplett ignoriert! knoteneinlesen ist eine procedure um die neu sortierte liste in einen listview zu schreiben (funktioniert fehlerfrei)

any ideas?

Chemiker 4. Aug 2009 23:14

Re: problem beim sortieren einer verketteten liste
 
Hallo arest,

ist eine etwas eigenwillige Formatierung des Quellcodes.

Ich kann jetzt nichts zu Deinem konkreten Problem beitragen.

Allerdings, sollte man die Abfragen nicht auf TRUE abfragen.

z.B.:

Delphi-Quellcode:
if (nachname=true)
              then begin
besser:

Delphi-Quellcode:
if nachname then
begin

Delphi-Quellcode:
if (Form1.RadioButton4.Checked=true)
                         then begin
besser:

Delphi-Quellcode:
if Form1.RadioButton3.Checked then
begin
  repeat
    lauf2:=lauf2.nachfolger;
  until ((lauf2.Daten.nachname > neu2.Daten.nachname) or (lauf2=ende2));
end;
Wenn der Ausdruck nach until komplett ausgewertet werden soll, sollte der Ausdruck komplett in eine Klammer gestellt werden.

Bis bald Chemiker

arest 4. Aug 2009 23:30

Re: problem beim sortieren einer verketteten liste
 
danke der antwort, aber das ändert nichts am problem... :(

Chemiker 4. Aug 2009 23:38

Re: problem beim sortieren einer verketteten liste
 
Hallo arest,

Dir ist aber bewusst, dass wenn man die Klammer nicht setzt, unter umständen nur der erste Teil der Abfrage ausgewertet wird?

Bis bald Chemiker

himitsu 4. Aug 2009 23:55

Re: problem beim sortieren einer verketteten liste
 
bei dem Code selber seh icht grad nicht so durch, als daß ich jetzt och Fehler finde (ist aber auch schon spät)

für alle deine RadioButons (1-6) kannst du auch eine einzige OnClick-Prozedur nutzen (einfach allein zuweisen)

das lauf2=ende2 würde ich zuerst abfragen, bevor ich auf lauf2 für dür den/die Vergleich(e) zugreife

dann nutzt du in der Sortieren-Funktion durcheinander diese Booleans und die CheckBoxen.
wenn du schon diese Booleans hast, warum nutzt du dann nicht nur diese?

und das mit dem True wurde schon gesagt.

ich hoff mal ich hab's auf das Wichtigste reduziert (an der Funktionsweise sollte sich nicht viel geändert haben, abgesehn vom lauf2=ende2)
Delphi-Quellcode:
procedure TForm1.RadioButtonClick(Sender: TObject);
begin
   nachname  := RadioButton1.Checked;
   vorname   := RadioButton2.Checked;
   kategorie := RadioButton5.Checked;
   geburtstag := RadioButton6.Checked;
   richtung  := RadioButton3.Checked;
   // RadioButton4 ist in der 3 enthalten, da ja wohl das Negative
   sortieren;
end;

procedure sortieren;
begin
   lauf:=TKnoten.Init;
   if (anfang.nachfolger<>ende)
   then begin
      anfang2:=TKnoten.Init;
      ende2:=TKnoten.Init;
      anfang2.nachfolger:=ende2;
      ende2.vorgaenger:=anfang2;

      lauf:=anfang;
      repeat
         lauf:=lauf.nachfolger;
         neu2:=TKnoten.Init;
         neu2.Daten:=lauf.Daten;
         lauf2:=anfang2;
         repeat
            lauf2:=lauf2.nachfolger;
         until (lauf2=ende2)
            or (    richtung and nachname  and (lauf2.Daten.nachname  > neu2.Daten.nachname))
            or (not richtung and nachname  and (lauf2.Daten.nachname  < neu2.Daten.nachname))
            or (    richtung and vorname   and (lauf2.Daten.vorname   > neu2.Daten.vorname))
            or (not richtung and vorname   and (lauf2.Daten.vorname   < neu2.Daten.vorname))
            or (    richtung and kategorie and (lauf2.Daten.kategorie > neu2.Daten.kategorie))
            or (not richtung and kategorie and (lauf2.Daten.kategorie < neu2.Daten.kategorie))
            or (    richtung and geburtstag and (lauf2.Daten.geburtstag > neu2.Daten.geburtstag))
            or (not richtung and geburtstag and (lauf2.Daten.geburtstag < neu2.Daten.geburtstag));
         lauf2.vorgaenger.nachfolger:=neu2;
         neu2.vorgaenger:=lauf2.vorgaenger;
         lauf2.vorgaenger:=neu2;
         neu2.nachfolger:=lauf2;
      until (lauf=ende.vorgaenger);
      anfang:=anfang2;
      ende:=ende2;
      knoteneinlesen;
   end;
end;
ich glaub so müßte man es noch kürzen können
Delphi-Quellcode:
repeat
   lauf2:=lauf2.nachfolger;
until (lauf2=ende2)
   or (nachname  and ((lauf2.Daten.nachname  < neu2.Daten.nachname)  xor richtung))
   or (vorname   and ((lauf2.Daten.vorname   < neu2.Daten.vorname)   xor richtung))
   or (kategorie and ((lauf2.Daten.kategorie < neu2.Daten.kategorie) xor richtung))
   or (geburtstag and ((lauf2.Daten.geburtstag < neu2.Daten.geburtstag) xor richtung));

nja, zumindestens isses jetzt etwas übersichtlicher und man findet womöglich den Fehler schneller,
außerdem nur ein Sortier-Code, statt 4 = 75% weniger Fehlerquellen :mrgreen:



um wieviele Listenelemente handelt es sich denn?
ich hab es mir letztens einfach gemacht

- Elemente gezählt
- dynamisches Array für die Elemente angelegt
- Array gefüllt
- in dem Array sortiert
- und dann über das Array neu neu verkettet

so geht das sortieren sogar etwas schneller, da man direkt über den Arrayindex sortieren und agieren kann
und sich wärend des Sortierens sich nicht um die Verknüfungen kümmern muß


[add]
sind RadioButton 3 und 4 unabhängig von den Anderen?
Gruppe 1 = 1, 2, 5 & 6
Gruppe 2 = 3 & 4

denn wenn in auch nur einer der Gruppen kein Button gecheckt ist, dann macht deine Version nix

Carsten1234 5. Aug 2009 09:46

Re: problem beim sortieren einer verketteten liste
 
Zitat:

Zitat von himitsu
ich hab es mir letztens einfach gemacht

:corky: :mrgreen:

p80286 5. Aug 2009 14:08

Re: problem beim sortieren einer verketteten liste
 
Also abgesehen davon, daß ich durch die Original Sourcen nicht so richtig durchsteige,
-ich hätte z.B. gerne die record-Definition gesehen-

Hinter RadoButton3 und Radiobutton4 werden keine Parameter gesetzt, wie z.B. hier
Delphi-Quellcode:
begin
      nachname:=false;
      vorname:=false;
      kategorie:=false;
      geburtstag:=true;
      sortieren;
   end;
In der Sortierroutine werden diese Werte aber abgefragt, das sieht mir sehr nach dem Ausnutzen von Seiteneffekten aus, da würde ich mich nicht wundern, wenn das Sortieren nicht klappt.

Gruß
K-H

arest 6. Aug 2009 11:10

Re: problem beim sortieren einer verketteten liste
 
erst mal großes dankeschön an himitsu! die funktion so wie du sie umgeschrieben hast, funktioniert soweit, allerdings nur soweit wie meine bisher auch :/ sie ist deutlich übersichtlicher und das fehler finden ist dadurch sicherlich leichter ;) radiobutton 1,2,5,6 sind in einer gruppe und 3,4 in einer anderen, wobei zu jeder zeit jeweils einer ausgewählt ist (vom formcreate an), d.h. daran kann es nicht liegen! weiterhin missachtet wird aufwärts/abwärts sortieren, sowie die sortierung nach geb/kategorie.... aus dem grund mal ne allgemeine frage dazu: wenn ich geburtstag als string reinsetzte, dann ist es klar, dass er nicht nach z.b. erst jahr, dann monat und dann tag sortiert, sondern einfach die zahlenwerte der reihe nach durchgeht. er müsste aber dennoch eigentlich zumindest in der hinsicht sortieren oder? d.h. ein geburtstag vom 21.03.1975 müsste dann einfach nach dem 13.03.1975 oder was auch immer gesetzt werden, da er einfach von vorne nach hinten den string durcharbeitet und 2 größer 1 ist, oder? warum zum geier reagiert er darauf also nicht? ich habe mit durchlauf per einzelanweisungen geprüft, ob die daten alle richtig eingelesen werden, was absolut der fall ist.... alles strings, alle gefüllt, keine fehler bis dahin! hier kurz die geforderte record methode...

Delphi-Quellcode:
type TDaten=record
   nachname,vorname,strasse,hausnummer,postleitzahl,wohnort,telefonhome,telefonhandy,telefonoffice,email,geburtstag,kategorie:string[50];
end;

type TKnoten=Class(TObject)
   Daten:TDaten;
   vorgaenger,nachfolger:TKnoten;
   Constructor Init;
end;

anschließend:
Delphi-Quellcode:
Constructor TKnoten.Init;
begin
   Daten.nachname:='';
   Daten.vorname:='';
   Daten.strasse:='';
   Daten.hausnummer:='';
   Daten.postleitzahl:='';
   Daten.wohnort:='';
   Daten.telefonhome:='';
   Daten.telefonhandy:='';
   Daten.telefonoffice:='';
   Daten.email:='';
   Daten.geburtstag:='';
   Daten.kategorie:='';
   vorgaenger:=NIL;
   nachfolger:=NIL;
end;

ins formcreate folgendes:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
   anfang:=TKnoten.Init;
   ende:=TKnoten.Init;
   anfang.nachfolger:=ende;
   ende.vorgaenger:=anfang;
   Radiobutton1.Checked:=true;
   Radiobutton3.Checked:=true;
   nachname:=true;
   vorname:=false;
   kategorie:=false;
   geburtstag:=false;
   richtung:=true;
end;

über eingabefelder werden die variablen gefüllt, wie bereits erwähnt problemfrei und anschließend über die sortieren funktion sortiert (habe jetzt die von himitsu drin). wo liegt die logik, dass nur vor/nachname funktionieren, obwohl keinerlei unterschiede in variablen/herangehensweise in der sortierfunktion vorliegen?! und warum reagiert die kacke auch in himitsu's version nicht auf auf/absteigend??

arest 6. Aug 2009 13:42

Re: problem beim sortieren einer verketteten liste
 
habe es noch mal ein wenig umgeschrieben, jedoch in dem sinne nicht wirklich was geändert, und jetzt funktioniert es einwandfrei.... danke für die bemügungen an alle! :) code im vorherigen eintrag gleich geblieben (record/knoten/formcreate) aber im sortierenbereich noch mal geändert wie folgt:

Delphi-Quellcode:
//********************************SORTIEREN FUNKTION*********************************
   //ausgewaehlt
   procedure ausgewaehlt;
   begin
      nachname:=Form1.RadioButton1.Checked;
      vorname:=Form1.RadioButton2.Checked;
      kategorie:=Form1.RadioButton5.Checked;
      geburtstag:=Form1.RadioButton6.Checked;
      richtung:=Form1.RadioButton3.Checked;
   end;
   //nachname
   procedure TForm1.RadioButton1Click(Sender: TObject);
   begin
      ausgewaehlt;
      sortieren;
   end;
   //vorname
   procedure TForm1.RadioButton2Click(Sender: TObject);
   begin
      ausgewaehlt;
      sortieren;
   end;
   //kategorie
   procedure TForm1.RadioButton5Click(Sender: TObject);
   begin
      ausgewaehlt;
      sortieren;
   end;
   //geburtstag
   procedure TForm1.RadioButton6Click(Sender: TObject);
   begin
      ausgewaehlt;
      sortieren;
   end;
   procedure TForm1.RadioButton3Click(Sender: TObject);
   begin
      ausgewaehlt;
      sortieren;
   end;
   procedure TForm1.RadioButton4Click(Sender: TObject);
   begin
      ausgewaehlt;
      sortieren;
   end;


//sortieren
procedure sortieren;
begin
   lauf:=TKnoten.Init;
   if (anfang.nachfolger<>ende)
   then begin
      anfang2:=TKnoten.Init;
      ende2:=TKnoten.Init;
      anfang2.nachfolger:=ende2;
      ende2.vorgaenger:=anfang2;

      lauf:=anfang;
      repeat
         lauf:=lauf.nachfolger;
         neu2:=TKnoten.Init;
         neu2.Daten:=lauf.Daten;
         lauf2:=anfang2;
         repeat
            lauf2:=lauf2.nachfolger;
         until (lauf2=ende2)
            or (    richtung and nachname  and (lauf2.Daten.nachname  > neu2.Daten.nachname))
            or (not richtung and nachname  and (lauf2.Daten.nachname  < neu2.Daten.nachname))
            or (    richtung and vorname   and (lauf2.Daten.vorname   > neu2.Daten.vorname))
            or (not richtung and vorname   and (lauf2.Daten.vorname   < neu2.Daten.vorname))
            or (    richtung and kategorie and (lauf2.Daten.kategorie > neu2.Daten.kategorie))
            or (not richtung and kategorie and (lauf2.Daten.kategorie < neu2.Daten.kategorie))
            or (    richtung and geburtstag and (lauf2.Daten.geburtstag > neu2.Daten.geburtstag))
            or (not richtung and geburtstag and (lauf2.Daten.geburtstag < neu2.Daten.geburtstag));
         lauf2.vorgaenger.nachfolger:=neu2;
         neu2.vorgaenger:=lauf2.vorgaenger;
         lauf2.vorgaenger:=neu2;
         neu2.nachfolger:=lauf2;
      until (lauf=ende.vorgaenger);
      anfang:=anfang2;
      ende:=ende2;
      knoteneinlesen;
   end;
end;
THX!


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:45 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