Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Sortieralgorithmus für Integer Werte optimieren


starsurfer - So 04.12.05 17:25
Titel: Sortieralgorithmus für Integer Werte optimieren
Ich hab mir jetzt mal einen eigenen Sortieralgorithmus für Integer Werte geschreiben... dieser ist nicht an bekannte Algorithmen angelehnt (glaub ich zumindest :wink: )

zur Zeit brauch mein Algo für 10000 Integer Zahlen zwischen 0.042 ~ 0.055 Sekunden; kommt immer darauf an wie viele Zahlen mehrfach enthalten sind...

hier mein Code:


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:
var
  unsortierte_liste,sortierte_liste:array of integer;
  bool_liste:array of bool;
  doppel_liste:array of array of integer;


procedure bool_sort;
var i,j,k,max,min,pos,d_pos,dl_laenge:integer;
    doppelt:bool;
begin
min:=unsortierte_liste[0];
max:=min;
pos:=0;
d_pos:=0;
dl_laenge:=1;
doppelt:=false;
for i:=0 to length(unsortierte_liste)-1 do
    begin
    if unsortierte_liste[i]<min then min:=unsortierte_liste[i];
    if unsortierte_liste[i]>max then max:=unsortierte_liste[i];
    end;
setlength(bool_liste,max-min+1);
setlength(doppel_liste,1,2);
for i:=0 to length(unsortierte_liste)-1 do
    begin
    if bool_liste[unsortierte_liste[i]-min]=true then
       begin
          for j:=0 to dl_laenge-1 do
              begin
              if unsortierte_liste[i]=doppel_liste[j,0then
                 begin
                 doppelt:=true;
                 d_pos:=j;
                 break;
                 end;
              end;
          if doppelt=true then
             begin
             inc(doppel_liste[d_pos,1]);
             end
            else
             begin
             doppel_liste[dl_laenge-1,0]:=unsortierte_liste[i];
             doppel_liste[dl_laenge-1,1]:=1;
             inc(dl_laenge);
             setlength(doppel_liste,dl_laenge,2);
             end;
          doppelt:=false;
       end;
    bool_liste[unsortierte_liste[i]-min]:=true;
    end;
setlength(sortierte_liste,length(unsortierte_liste));
for i:=0 to length(bool_liste)-1 do
    begin
    if bool_liste[i]=true then
       begin
            for j:=0 to length(doppel_liste)-1 do
                begin
                if i+min=doppel_liste[j,0then
                   begin
                        for k:=0 to doppel_liste[j,1]-1 do
                            begin
                            sortierte_liste[pos]:=i+min;
                            inc(pos);
                            end;
                   break;
                   end;
                end;
       sortierte_liste[pos]:=i+min;
       inc(pos);
       end;
    end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var j,zahl:integer;
    start,ende,f:int64;
begin
zahl:=strtoint(edit1.text);
randomize;
setlength(unsortierte_liste,zahl);
for j:=0 to zahl-1 do
    begin
    unsortierte_liste[j]:=random(zahl*10);
    end;
QueryPerformanceCounter(Start);
bool_sort;
QueryPerformanceCounter(ende);
QueryPerformanceFrequency(f);
showmessage(floattostr((ende-start)/f));
setlength(bool_liste,0);
setlength(doppel_liste,0,2);
setlength(sortierte_liste,0);
setlength(unsortierte_liste,0);
end;


Funktionsprinzip:
1. die min. und max. Zahl wird ermittelt
2. daraus wird eine boolean Tabelle erstellt die (max-min+1) lang ist
3. der unsortierte Array wird Element für Element abgegrasst und dabei wird die integer Zahl einfach als Index für den boolean Array genommen, der dann auf True gesetzt wird (z.B I-zahl=100 -> boolen_array[100]=true)
4. es wird auf doppelte Zahlen geprüft, sollte es doppelte Zahlen geben wird diese Zahl in einem zusätzlichen Array mit Anzahl gespeichert
5. am Ende wird der boolean Array ausgewerte und die Zahlenwerte werden in den sortierten Array geschreiben

ich hoffe das war halbwegs klar beschreiben und ihr seit nicht allzu verwirrt... :)

ich weis das dieser Algorithmus nicht gerade RAM sparend ist..aber darum ging es mir weniger(da kann man sicher auch noch was drehen, zB für die sortierten Werte einfach den unsortierten Array überschreiben statt ein neuen Array zu nutzen...)

Hauptsächlich gings mir natürlich um Geschwindigkeit.

Was meint ihr dazu und wo kann man noch was am Speed drehen?


//EDIT: auch BucketSort genannt


Horst_H - So 04.12.05 17:41

Hallo,

ist das nicht einfach ein Bucket-Sort?
Statt array of Boolean einfach ein array of cardinal vorher auf 0 setzen und entsprechend erhoehen.
Das Sortierverfahren geht aber nur bei kleinen Differenzen zwischen min und max.

Gruss Horst


starsurfer - So 04.12.05 17:45

Array of Boolean hab ich genommen weil Boolean wesentlich weniger Platz brauch als Cardinal - damit ich wenigsten etwas größere Zahlen sortieren kann :P

Bucket-Sort hab ich noch nit gekannt...
hab ich gleich mal gegogglet...
scheint genau Das zu sein was ich gemacht hab