Seite 1 von 2
sortieren Arrays über Pointer
Verfasst: 19.07.2009 08:50
von PeterJ
Ich habe ein kleines Verständnisproblem mit Arrays und deren Verwendung mittels Pointern.
Als Ausgangslage habe ich mehrere (viele) Arrays, die wie folgt definiert sind:
Code: Alles auswählen
Global Dim ArrayString00.s(1)
Global Dim ArrayString01.s(1)
...
diese Arrays werden dynamische verwaltet und ggf. mit REDIM erweitert/verkürzt. Im Programm spreche ich sie mit Pointern und einer Struktur an:
Verwendet werden sie z.B. wie folgt Einlesen Datei in Array:
Code: Alles auswählen
*toArray.StringArray=ArrayDef(toArray)\ArrayAddress
While Eof(0)=0 ; Read until EOF
i+1
*toArray\text[i]=ReadString(0)
Wend
Das funktioniert alles ganz perfekt. Nun will ich noch eine SORT Funktion einbauen. und habe keine Idee wie ich den Sortaufruf machen soll:
Syntaktisch muß es ja so sein:
Wie mache ich das aber wenn ich nur die Adresse kenne und nur über Pointer und Struktur zugreifen kann?
sowas wie:
geht leider nicht. Wie mache ich es richtig?
... und weil wir dabei sind, kann mir jemand zeigen wo die Dokumentation über die Array Adressierung mit
(in *pointer\variable) steht. Ich verwende sie, weil ich sie mir jemand in einem früheren Posting gezeigt hat. Der eigentliche Unterschied zur "(i)" Notation ist mir aber nicht klar.
Peter
Verfasst: 19.07.2009 10:17
von Kaeru Gaman
wenn du ReDim benutzt um sie zu verlängern/verkürzen, warum benutzt du dann nicht auch den klassischen Aufruf im Sort?
... mir ist sowieso nicht einleuchtend, warum du pointer für deinen zugriff benutzt...
wegen der unterschiedlichen namen?
warum benutzt du nicht ArrayString.s(0,1), ArrayString.s(1,1) statt ArrayString00.s(1), ArrayString01.s(1) ?
Verfasst: 19.07.2009 10:30
von cxAlex
Wenn du es unbedingt mit Pointern machen willst musst du dir selbst einen Sortieralgorythmus basteln. Ich hab hier mal nen angepassten Counting Sort für dich.
Ist besonders schnell wen der Bereich der zu sortierenden Zahlen klein ist:
Du musst ihn nur noch so anpassen das er nach Characters sortiert.
Code: Alles auswählen
Structure IntArray
i.i[0]
EndStructure
Procedure CountingSort(*Array.IntArray, ArraySize)
Protected *sortedArray.IntArray
Protected i, j, fillheight, cnt, MaxSize, MinSize
MaxSize = *Array\i[0]
MinSize = MaxSize
For i = 1 To ArraySize-1
If *Array\i[i]>MaxSize
MaxSize = *Array\i[i]
EndIf
If *Array\i[i]<MinSize
MinSize = *Array\i[i]
EndIf
Next
*sortedArray = AllocateMemory(((MaxSize-MinSize) + 1)*SizeOf(Integer))
For i = 0 To ArraySize-1
*sortedArray\i[*Array\i[i]-MinSize] + 1
Next
For i = MinSize To MaxSize
cnt = *sortedArray\i[i-MinSize]-1
For j = 0 To cnt
*Array\i[fillheight] = i
fillheight + 1
Next
Next
FreeMemory(*sortedArray)
EndProcedure
#AnzEintrys = 20000000
#Min = 100
#Max = 355
Define *tArray.IntArray = AllocateMemory(#AnzEintrys*SizeOf(Integer))
For i = 0 To #AnzEintrys-1
*tArray\i[i] = Random(#Max-#Min) + #Min
;Debug *tArray\i[i]
Next
t = ElapsedMilliseconds()
CountingSort(*tArray, #AnzEintrys)
t1 = ElapsedMilliseconds()-t
MessageRequester("", Str(t1) + " ms")
For i = 0 To #AnzEintrys-1
Debug *tArray\i[i]
Next
Gruß, Alex
Verfasst: 19.07.2009 10:48
von PeterJ
Kaeru Gaman hat geschrieben:wenn du ReDim benutzt um sie zu verlängern/verkürzen, warum benutzt du dann nicht auch den klassischen Aufruf im Sort?
... mir ist sowieso nicht einleuchtend, warum du pointer für deinen zugriff benutzt...
wegen der unterschiedlichen namen?
warum benutzt du nicht ArrayString.s(0,1), ArrayString.s(1,1) statt ArrayString00.s(1), ArrayString01.s(1) ?
Ist etwas kompliziert, zu erklären: Ich steuere von Außen die Operationen die mit dem Array ausgeführt werden sollen. Als Beispiel ich habe Float Arrays, mit denen ich Matrix Operationen ausführe. Ich sage also:
1. ReadFloat(array-nummer-1,File1)
2. ReadFloat(array-nummer-2,File2)
3. Multiply(array-nummer-1,array-nummer-2)
(Die 2. Dimension der Matrix simuliere ich)
Das heißt die Verarbeitungsanweisung wird über eine Eingabedatei angestoßen. Das bedeutet konkret, ich kenne nur die relative array-nummer und ordne intern die Array Addresse zu.
Für String- und Numeric Arrays verfahre ich entsprechend.
Die 2. Dimension geht deshalb nicht weil die Arrays unterschiedlich lang sind und ich dann nicht die Möglichkeit habe mit REDIM individuell zu dimensionieren.
@cxAlex: Danke, das wird dann wohl der Weg sein, den ich beschreiten muß.
Verfasst: 19.07.2009 11:03
von cxAlex
Ich hab den Algo nochmal schnell verbessert, wie man den noch schneller machen könnte seh ich im Moment nicht:
Code: Alles auswählen
Structure IntArray
i.i[0]
EndStructure
Procedure CountingSort(*Array.IntArray, ArraySize, MaxSize = -1)
Protected *sortedArray.IntArray
Protected i, j, fillheight, cnt
ArraySize-1
If MaxSize = -1
MaxSize = *Array\i[0]
For i = 1 To ArraySize
If *Array\i[i]>MaxSize
MaxSize = *Array\i[i]
EndIf
Next
EndIf
*sortedArray = AllocateMemory((MaxSize + 1)*SizeOf(Integer))
For i = 0 To ArraySize
*sortedArray\i[*Array\i[i]] + 1
Next
For i = 0 To MaxSize
cnt = *sortedArray\i[i]
For j = 1 To cnt
*Array\i[fillheight] = i
fillheight + 1
Next
Next
FreeMemory(*sortedArray)
EndProcedure
#AnzEintrys = 20000000
#Min = 100
#Max = 355
Define *tArray.IntArray = AllocateMemory(#AnzEintrys*SizeOf(Integer))
For i = 0 To #AnzEintrys-1
*tArray\i[i] = Random(#Max-#Min) + #Min
;Debug *tArray\i[i]
Next
t = ElapsedMilliseconds()
CountingSort(*tArray, #AnzEintrys, #Max)
t1 = ElapsedMilliseconds()-t
MessageRequester("", Str(t1) + " ms")
For i = 0 To #AnzEintrys-1
Debug *tArray\i[i]
Next
Gruß, Alex
Verfasst: 27.07.2009 17:43
von PMV
PeterJ hat geschrieben:
Die 2. Dimension geht deshalb nicht weil die Arrays unterschiedlich lang sind und ich dann nicht die Möglichkeit habe mit REDIM individuell zu dimensionieren.
Redim funktioniert doch mit Mehrdimensionalen Arrays, du kannst damit
halt nur die letzte Dimension ändern, aber genau das ist auch jetzt der
fall, wenn du das so umständlich machst. Die erste Dimension ist halt die
Anzahl deiner Variablen, die du von Hand geschrieben hast. Die kannst zur
laufzeit auch nicht löschen oder erstellen.
MFG PMV
Verfasst: 29.07.2009 13:42
von PeterJ
PMV hat geschrieben:[Redim funktioniert doch mit Mehrdimensionalen Arrays, du kannst damit halt nur die letzte Dimension ändern, aber genau das ist auch jetzt der fall, wenn du das so umständlich machst. Die erste Dimension ist halt die Anzahl deiner Variablen, die du von Hand geschrieben hast. Die kannst zur laufzeit auch nicht löschen oder erstellen.
MFG PMV
nicht ganz, bei 2-dimensionalen Arrays hätte ich z.B. die Situation:
array(1,n1) n1=1,2, ... 10
array(2,n2) n2=1,2, ... 100
array(3,n3) n3=1,2,...1000
Nachdem ein REDIM immer nur die letzte Dimension ändern kann, kann ich nur REDIM ARRAY(3,1000) als den insgesamt maximalen Wert angeben.
Ich könnte nicht sagen
REDIM ARRAY(1,10)
REDIM ARRAY(2,100)
REDIM ARRAY(3,1000)
Verfasst: 29.07.2009 13:43
von Kaeru Gaman
ReDim braucht du aber nur dann, wenn du den Inhalt buffern willst.
wenn der dir egal ist, kannst du einfach Dim benutzen, und du erhältst ein neues leeres Array mit dem selben Namen.
Verfasst: 30.07.2009 17:06
von PMV
PeterJ hat geschrieben:Nachdem ein REDIM immer nur die letzte Dimension ändern kann, kann ich nur REDIM ARRAY(3,1000) als den insgesamt maximalen Wert angeben.
Ich könnte nicht sagen
REDIM ARRAY(1,10)
REDIM ARRAY(2,100)
REDIM ARRAY(3,1000)
Stimmt, und du schreibst dein Programm für einen speziellen Rechner, der
nicht all so viel RAM hat?
9.990 + 9.900 = 19.890 Byte zu viel ... naja gut, wenn du dafür lieber
Spagetticode produzierst, ist dir natürlich erlaubt.

kleiner Spaß
MFG PMV
Verfasst: 30.07.2009 22:30
von PeterJ
PMV hat geschrieben:Stimmt, und du schreibst dein Programm für einen speziellen Rechner, der nicht all so viel RAM hat?
9.990 + 9.900 = 19.890 Byte zu viel ... naja gut, wenn du dafür lieber
Spagetticode produzierst, ist dir natürlich erlaubt.

kleiner Spaß
MFG PMV
Ausgangslage war sortieren von String Arrays, insoweit ist mein REDIM natürlich nicht korrekt und was Dimensionen anbelangt nur beispielhaft. Real würde er in etwa so aussehen:
REDIM ARRAY.S(100,n), wobei n=1,...1.500.000 (derzeit größter Fall den ich hatte). Stringlänge im Schnitt 60 Bytes.
Das macht also 100*1.500.000*61 macht 8.5 GB, das könnte ein normal XP nicht addressieren. Die Applikation selbst braucht meist nur 1 ganz großen Array, und mehrere kleinere Kontrollarrays.
Dabei entsteht nicht notwendigerweise Spagetticode, das alles läßt sich wunderbar modularisieren.