Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Probleme bei Sortieralgorithmus ud der einbindung von arrays


Orpi - Do 15.09.05 15:30
Titel: Probleme bei Sortieralgorithmus ud der einbindung von arrays
hi,

ich bin grade dabei ein programm zu schreiben in dem ich einige sortierverfahren ausprobieren möchte. nun habe ich aber probleme im ansatz. ich möchte zahlen aus einem textfeld in ein array einlesen,sortieren und ausgeben. dabei soll aber die anzahl der zu sortierenden elemente schon im aufruf der procedure festgelegt werden(vielleicht auch schon vom benutzer) unabhängig von der anzahl der eingegebenen elemente(dh wenn ich 10 elemente eingebe kann ich trotzdem bestimmten ob nun vom 1. bis zum 10. oder nur vom 3 bis zum 5 sortiert wird un der rest unberührt bleibt).

ich bin nicht grad ein profi in sachen delphi und daher kann es sein das ich wirklich doofe fehler gemacht hab und deswegen nicht weiterkomme.

vielleicht kann mir jemand helfen...

bitte besoderes augenmerk auf die procedure einlesen und bubblesort legen

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:
unit Form;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  sort, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    eingabe: TEdit;
    Memo1: TMemo;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button2Click(Sender: TObject);

 var
 i:integer;
begin

for i:=1 to MaxAnzahl do
 Randomize;

end;

procedure TForm1.Button1Click(Sender: TObject);
var
SF:tsortfeld;
begin
SF:=einlesen(eingabe.text);
bubblesort(1,maxanzahl,SF);
end;

end.





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:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
unit Sort;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
   StdCtrls;

const
  MaxAnzahl = 25;

type
  TElement = integer;
  TSortFeld = array[0..Maxanzahl-1of TElement;


//function pruef(s:string):integer;
procedure bubblesort(Anfang,Ende: integer; VAR SF: TSortFeld);
function einlesen(s: string):TSortFeld;

implementation


{function pruef(s:string):integer;
var
 i:integer;
begin
  for i:=1 to length(s)do
    if not strtoint(s[i]) in [0..10] then result:=result+1;

  result:=0;
end;  }





procedure bubblesort(Anfang,Ende: integer; VAR SF: TSortFeld);
var
  i,h:integer;
begin

  for i:=anfang to ende do
    begin
     if SF[i] > SF[i+1then
      begin
        h:=SF[i];
        SF[i]:=SF[i+1];
        SF[i+1]:=h;
      end;

   end;
end;


function einlesen(s: string):TSortFeld;
var
  i,j:integer;
  SF:Tsortfeld;
begin
  i:=1;
  j:=0;
  repeat
    inc(j);
    repeat
      SF[j]:=(strtoint(s[i]));
      inc(i);
    until S[i]=' ';
  until i=length(s);
  einlesen:=SF;
end;

end.


Moderiert von user profile iconTino: Überflüssige Zeilenumbrüche entfernt.


smiegel - Do 15.09.05 15:39

Hallo,

Dein Bubblesort-Algo ist nicht ganz korrekt.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure bubblesort(Anfang, Ende:Integer; var SF:TSortFeld);  
var  
  i, j, h:Integer;  
begin  
  for i:=anfang to ende-1 do  
    for j:=anfang+1 to ende do
     if (SF[i]>SF[j]) then  
     begin  
       h:=SF[i];  
       SF[i]:=SF[j];  
       SF[j]:=h;  
     end// if
  end// for
end;


Orpi - Do 15.09.05 18:00

ah..ich seh schon meinen fehler...der geht ja nur einmal durch...

vierlleicht kann mir jemand noch beim aufruf der procedure helfen...ich hab damit auch ein problem weil ich nicht weiss
wie ich die variablen konstante im aufruf einbinden soll...


Narses - Do 15.09.05 18:12

Moin!

Was willst du damit bewirken?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.Button2Click(Sender: TObject);  
 var  
 i:integer;  
begin  
for i:=1 to MaxAnzahl do  
 Randomize;  
end;

Es reicht, wenn du einmal im FormCreate Randomize aufrufst, das wird nicht besser, wenn man das mehrmals tut... :wink:

Soll dieser Code eine Folge von durch Leerzeichen getrennten Zahlen in ein Array umwandeln?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function einlesen(s: string):TSortFeld;  
var  
  i,j:integer;  
  SF:Tsortfeld;  
begin  
  i:=1;  
  j:=0;  
  repeat  
    inc(j);  
    repeat  
      SF[j]:=(strtoint(s[i]));  
      inc(i);  
    until S[i]=' ';  
  until i=length(s);  
  einlesen:=SF;  
end;

Das wird so nicht funktionieren. Mach dich mal über StringListen und .CommaText dieser schlau. Dann kannste den übergebenen String sehr einfach damit zerlegen und mit StrToIntDef(SL.String[i],0), wobei SL die StringListe ist, durchgehen.

cu
Narses


Orpi - Do 15.09.05 18:41

der ober quellcode kann auch in kommentak klammern..sind reste von nem anderen code


warum funktioniert das mit dem umwandeln nicht? ich fand da war ne ganz gut idee..weis aber auch nich warums nich geklappt hat


Narses - Do 15.09.05 20:13

Moin!

user profile iconOrpi hat folgendes geschrieben:
der ober quellcode kann auch in kommentak klammern..sind reste von nem anderen code

Du wirkst etwas unorganisiert... :? :wink:

user profile iconOrpi hat folgendes geschrieben:
warum funktioniert das mit dem umwandeln nicht? ich fand da war ne ganz gut idee..weis aber auch nich warums nich geklappt hat

Wieso ist´s eine gute Idee, wenn´s doch nicht funktioniert? :wink:

Probier das mal so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
function Einlesen(S: String): TSortFeld;
  var    
    i,j: Integer;    
    SL: TStringList;
begin    
  SL := TStringList.Create;
  SL.CommaText := S;
  for i := 0 to SL.Count-1 do begin
    j := StrToIntDef(SL.Strings[i],0);
    ShowMessage('Wert Nr. '+IntToStr(i)+' : '+IntToStr(j));
    if (i <= High(Result)) then
      Result[i] := j;
  end;
  SL.Free;
end;

cu
Narses


Orpi - Do 15.09.05 20:39

ne kleiner erklärung wär nich schlecht :wink: :oops:


Narses - Do 15.09.05 20:46

Moin!

OK, hier die kommentierte Version:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
function Einlesen(S: String): TSortFeld;  
  var      
    i,j: Integer;      
    SL: TStringList;  
begin      
  SL := TStringList.Create; // StringListe erzeugen
  SL.CommaText := S; // die Zahlen aufspalten
  for i := 0 to SL.Count-1 do begin // alle Elemente der Stringliste durchgehen
    j := StrToIntDef(SL.Strings[i],0); // Zahl im Textformat in einen Integer konvertieren; bei Fehler 0 nehmen
    ShowMessage('Wert Nr. '+IntToStr(i)+' : '+IntToStr(j)); // Testausgabe, kann weg
    if (i <= High(Result)) then // wenn die Zahl noch in das TSortFeld rein passt...
      Result[i] := j; // übernehmen
  end;  
  SL.Free; // StringListe freigeben
end;

cu
Narses


Orpi - Fr 16.09.05 10:17

mensch..das sieht ja recht kompliziert aus. gibs nich noch irgendeine andere lösung
mehrstellige zahlen aus einem textfeld oder einer listbox zu sortieren?
also das sie dann in ein array geschrieben werden müssen it mir schn klar.
nur wie kommen sie da am besten rein? das problem sind ja auch eben diese mehrstelligen zahlen. ich wil auch nicht unbedingt sachen nehmen die ich nicht kenne..es muss ja auc h so funktionieren ohne .cammatext und stringlist..oder nicht?


Narses - Fr 16.09.05 10:30

Moin!

user profile iconOrpi hat folgendes geschrieben:
mensch..das sieht ja recht kompliziert aus.

Kompliziert?! Die drei Zeilen... :gruebel:

user profile iconOrpi hat folgendes geschrieben:
gibs nich noch irgendeine andere lösung
mehrstellige zahlen aus einem textfeld oder einer listbox zu sortieren?

Hmm, mal langsam, Textfelder und Listboxen sind ja nun mal bei leibe nicht dasselbe! Die Lösung mit dem Textfeld wird auf mehr oder weniger sowas rauslaufen, wie das, was ich da geschrieben habe.

Bei einer Listbox haste doch schon die einzelnen Strings in dem Items der Listbox, dann kannste dir die StringListe sparen. Dafür haste dann aber mehr Arbeit beim Editieren der Einträge.

user profile iconOrpi hat folgendes geschrieben:
also das sie dann in ein array geschrieben werden müssen it mir schn klar.
nur wie kommen sie da am besten rein? das problem sind ja auch eben diese mehrstelligen zahlen.

So, wie oben beschrieben. Der entscheidende Teil ist doch nur das StrToIntDef(), der Rest ist ja praktisch nur dazu da, den Text in einzelne Zahlen zu zerlegen. :wink:

user profile iconOrpi hat folgendes geschrieben:
ich wil auch nicht unbedingt sachen nehmen die ich nicht kenne..es muss ja auc h so funktionieren

Schon klar, sonst merkt der Lehrer, dass es nicht von dir ist... :wink: dann streng dich auch mal ein bischen an, sonst merkt der was wirklich noch! :D

cu
Narses


Orpi - Fr 16.09.05 11:08

mal im klartext..hast mich ja durchschaut :shock:

ich soll ein programm schreiben das mehrer sortieralgorithmen ineinander vereint und zufällig zahlen erzeugt...blabla

die algorithmen sind nicht das problem..die sind fast alle schon fertig.
uns wurde der procedurkopf

Delphi-Quelltext
1:
procedure xyzsort(anfang,end:integer; VAR SF : TSortFeld);                    

vorgegeben

undn wie schon gesagt haperts einfach nur am benutzen dieser doofen(und doch sehr nützlichen) arrays. es muss ja zu machen sein mit meinen kenntnissen...sonts würde die aufgabe ja nicht gestellt werden..aba mir fehlt der ansatz


wie kann man das denn mit der listbox macehn?
ich mein was reinschreiben kann ich ja
aber wie behandelt man die einzelnen zeilen? wie stellen im string?


Narses - Fr 16.09.05 11:32

Moin!

user profile iconOrpi hat folgendes geschrieben:
mal im klartext..hast mich ja durchschaut :shock:

:mrgreen: Mach dir nix draus, du bist nicht der erste Schüler hier, und die Aufgaben sind mal ziemlich "aussagekräftig"...

user profile iconOrpi hat folgendes geschrieben:
ich soll ein programm schreiben das mehrer sortieralgorithmen ineinander vereint und zufällig zahlen erzeugt...blabla
die algorithmen sind nicht das problem..die sind alle schon fertig.

Dann zeig diese doch mal, bisher haste ja nur BubbleSort "rausgerückt". Würde zumindest mir zeigen, dass du dich auch für das Programm einsetzt.

user profile iconOrpi hat folgendes geschrieben:
uns wurde der procedurkopf

Delphi-Quelltext
1:
procedure xyzsort(anfang,end:integer; VAR SF : TSortFeld);                    

vorgegeben

undn wie schon gesagt haperts einfach nur am benutzen dieser doofen(und doch sehr nützlichen) arrays. es muss ja zu machen sein mit meinen kenntnissen...sonts würde die aufgabe ja nicht gestellt werden..aba mir fehlt der ansatz

Kommst du nun mit den Arrays und dem Prozeduraufruf nicht klar, oder mit der GUI, sprich, dem Ein-/Ausgeben der Zahlen ins/aus dem Array? :gruebel:

user profile iconOrpi hat folgendes geschrieben:
wie kann man das denn mit der listbox macehn?
ich mein was reinschreiben kann ich ja
aber wie behandelt man die einzelnen zeilen?

Z.B. so:

Delphi-Quelltext
1:
2:
for i := 0 to ListBox1.Items.Count-1 do
  ShowMessage(ListBox1.Items.Strings[i]);

cu
Narses


Orpi - Sa 17.09.05 18:08

gut..dann hier mal meine sort algothimen


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:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
procedure Selectionsort(anfang,ende:integer;Var SF:TSortfeld);

var
 hSF:TSortFeld;
 i, j: Integer;
begin
  for i:=anfang to ende-1 do
  begin

    for j:= i+1 To ende do
      if (SF[j] < SF[i]) then hSF[i]:=SF[j];
    end;//of for
  SF:=hSF;
end;


procedure InsertionSort (anfang,ende:integer;VAR SF : TSortFeld);
var
  i,j : Integer;
  hSF: TSortFeld;
begin
  for i:=anfang to ende-1 do
    for j := i downto 1 do
      if (SF[j] > SF[j+1]) then
        begin
         hSF[j]:=SF[j];
         SF[j]:=SF[j+1];
         SF[j+1]:=hSF[j];
        end;

procedure shakerSort(anfang,ende:integer; VAR SF : TSortFeld);
 var
 j,k:integer;
 hSF:TSortFeld;
begin

repeat
  for j:=anfang downto ende do
  begin
    if SF[j-1]>SF[j] then
    begin
      hSF[j]:=SF[j-1];
      SF[j-1]:=SF[j];
      SF[j]:=hSF[j];
      k:=j;
    end;
  end;
  ende:=k+1;
  for j:=ende to r do
  begin
    if h[j-1]>h[j] then
    begin
      hSF[j]:=SF[j-1];
      SF[j-1]:=SF[j];
      SF[j]:=hSF[j];
      k:=j;
    end;
  end;
  r:=k-1;
  until ende>anfang;
end;


procedure quicksort(anfang,ende:integer;Var SF:TSortfeld)
  var
    links, rechts, vergleichswert: integer;
begin
 if ende > anfang then
 begin
  links := anfang;
  rechts := ende;
  vergleichswert := (anfang + ende) DIV 2;
  while links <= rechts DO
  begin
   if (SF[links] >= SF[vergleichswert]) and (SF[rechts] <= SF[vergleichswert]) then
   begin
    tausche(SF[links],SF[rechts]);
    if links = vergleichswert then
     vergleichswert := rechts else
     if rechts = vergleichswert then
      vergleichswert := links;
    if links < ende then inc(links);
    if rechts > anfang then dec(rechts);
   end else
    if SF[links] >= SF[vergleichswert] then dec(rechts) else inc(links);
  end;

  quick_sort(anfang,rechts);

  quick_sort(links,ende);

 end;
end;


da folgt noch merge sort...den hab ch nocht nicht...:?

ich meinte das ich mit der gui nicht klarkomme...


Narses - So 18.09.05 11:45

Moin!

user profile iconOrpi hat folgendes geschrieben:
gut..dann hier mal meine sort algothimen

Danke.

user profile iconOrpi hat folgendes geschrieben:
ich meinte das ich mit der gui nicht klarkomme...

OK, planen wir erstmal was:

Du hast ein statisches Array (mit fester Anzahl Elemente). Daraus folgt, du solltest in der GUI das Erscheinungsbild und die Editiermöglichkeiten so wählen, dass immer die Gesamtanzahl der Arrayelemente (also das ganze Array) betroffen ist und der User keine Möglichkeit hat, die Anzahl der Elemente zu verändern.

Mir fallen da auf Anhieb zwei Controls ein, die man dafür recht gut gebrauchen könnte: Listbox oder StringGrid. Ich mache mal einen Vorschlag für die ListBox, die hast du ja auch schon selbst vorgeschlagen.

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:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
unit Unit1;

interface

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

const
  MaxAnzahl = 25;

type
  TElement = Integer;
  TSortFeld = Array[0..MaxAnzahl-1of TElement;

  TForm1 = class(TForm)
    ListBox1: TListBox;
    BtnZufall: TButton;
    BtnAufsteigend: TButton;
    BtnAbsteigend: TButton;
    BtnEingabe: TButton;
    BtnSort: TButton;
    procedure FormCreate(Sender: TObject);
    procedure UpdateSortFeld;
    procedure BtnZufallClick(Sender: TObject);
    procedure BtnAufsteigendClick(Sender: TObject);
    procedure BtnAbsteigendClick(Sender: TObject);
    procedure BtnEingabeClick(Sender: TObject);
    procedure BtnSortClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    SortFeld: TSortFeld;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// Array in die GUI übertragen
procedure TForm1.UpdateSortFeld;
  var
    i: Integer;
begin
  ListBox1.Clear;
  for i := 0 to High(SortFeld) do
    ListBox1.Items.Add(IntToStr(SortFeld[i]));
end;

// Bei Programmstart einmal den Button Zufall "drücken"
procedure TForm1.FormCreate(Sender: TObject);
begin
  Randomize; // zufälliger Zufall
  BtnZufallClick(Self);
end;

// Array mit zufälligen Zahlen füllen
procedure TForm1.BtnZufallClick(Sender: TObject);
  var
    i: Integer;
begin
  for i := 0 to High(SortFeld) do
    SortFeld[i] := Random(100);
  UpdateSortFeld;
end;

// Array mit aufsteigenden Zahlen füllen
procedure TForm1.BtnAufsteigendClick(Sender: TObject);
  var
    i: Integer;
begin
  for i := 0 to High(SortFeld) do
    SortFeld[i] := i;
  UpdateSortFeld;
end;

// Array mit absteigenden Zahlen füllen
procedure TForm1.BtnAbsteigendClick(Sender: TObject);
  var
    i: Integer;
begin
  for i := 0 to High(SortFeld) do
    SortFeld[i] := High(SortFeld) -i;
  UpdateSortFeld;
end;

// manuelle Eingabe der Zahlen ins Array
procedure TForm1.BtnEingabeClick(Sender: TObject);
  var
    i: Integer;
    Zahl: String;
begin
  i := 0;
  while ( (i <= High(SortFeld))
        and
          InputQuery(IntToStr(i+1)+'. Zahl eingeben','Wert: ',Zahl) ) do begin
    SortFeld[i] := StrToIntDef(Zahl,0);
    Inc(i);
  end;
  UpdateSortFeld;
end;

// Array sortieren...
procedure TForm1.BtnSortClick(Sender: TObject);
begin
  // Dinge mit dem Array tun...
  // dann die GUI anpassen:
  UpdateSortFeld;
end;

end.

cu
Narses


Orpi - So 18.09.05 13:20

danke..das hat mit sehr geholfen...besonders die update procedur.

nur ein problem besteht im moment:
wenn ich das arry mit zahlen befüllt habe und sie dann ausgebe kommen zahlen
im bereich des gesammten integer...und wenn ich dann nochmal auf den button klicke
ändern sich höchstens 2 zahlen


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure TForm1.ZufallClick(Sender: TObject);
var
  i:integer;
  SF:TSortFeld;
begin

for i:=0 to high(SF) do
SF[i]:=(random(100));
updateSFein;
end;

procedure TForm1.UpdateSFein;  // übertragen des array in gui
  var
    SF: TSortFeld;
    i: Integer;
begin
  Eingabe.Clear;
  for i := 0 to High(SF) do
    eingabe.Items.Add(IntToStr(SF[i]));
end;


Orpi - So 18.09.05 13:26

hat sich erledigt...

ich hab SF nich global sondern in jeder procedur einzeln deklariert :lol: :oops:


aber wenn ich bubblesort durchlaufen lasse dann sind die zahlen richtig sortiert aber ganz am ende und am anfang steht dann immer noch ein zahl...die nicht sortiert ist


Narses - So 18.09.05 21:54

Moin!

user profile iconOrpi hat folgendes geschrieben:
aber wenn ich bubblesort durchlaufen lasse dann sind die zahlen richtig sortiert aber ganz am ende und am anfang steht dann immer noch ein zahl...die nicht sortiert ist

Ja, und, Code? :wink:

cu
Narses


Orpi - Mo 19.09.05 20:49

alles im lot