Problem mit Tlist im Type

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

Schrolli

Betreff: Problem mit Tlist im Type

BeitragDi, Jan 26, 2016 0:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe ein Problem mit der Benutzung von Tlist in einem Type

Follgende Ausgabe:
Code: [AUSKLAPPEN]
Executing:untitled1.exe
New TTileEngine created
New TTileLayer created: Test Layer1
New TTileLayer created: Test Layer2
New TTileLayer created: Test Layer3



exit

Komischerweise hat die Liste wie im Code zu erwarten 3 Einträge. Die in name gespeicherten Strings sind aber weg. Was läuft denn hier schief?

BlitzMax: [AUSKLAPPEN]

Local tE:TTileEngine = New TTileEngine.Create(150, 150)
tE.newLayer("Test Layer1")
tE.newLayer("Test Layer2")
tE.newLayer("Test Layer3")

For Local L:TTileLayer = EachIn tE.Layer
Print L.name
Next

Print "exit"



Type TTileEngine

Field windowX:Int
Field windowY:Int

Field Layer:TList = New TList


'Constructor
Method Create:TTileEngine(windowX:Int, windowY:Int)
Local constructor:TTileEngine = New TTileEngine

Print "New TTileEngine created"
Self.windowX = windowX
Self.windowY = windowY

Return constructor
End Method


Method newLayer(name:String)
Local lay:TTileLayer = New TTileLayer.Create(name)
Self.Layer.AddLast(lay)
End Method

End Type



Type TTileLayer
Field name:String

'Constructor
Method Create:TTileLayer(name:String)
Local constructor:TTileLayer = New TTileLayer

Print "New TTileLayer created: " + name
Self.name = name

Return constructor
End Method

End Type


Grüße

Midimaster

BeitragDi, Jan 26, 2016 9:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Du mischt da was....

Auf der einene Seite hast Du in der Methode "TTileEngine-Create" die lokale variable CONSTRUCTOR erstellt, die Du auch zurückgibts. Aber die Werte weist Du SELF zu. Dies geht sogar schon beim Wert WINDOWX schief:

teste dies:
BlitzMax: [AUSKLAPPEN]
SuperStrict
Local tE:TTileEngine = New TTileEngine.Create(150, 150)
Print "X=" + te.windowX

tE.newLayer("Test Layer1")
tE.newLayer("Test Layer2")
tE.newLayer("Test Layer3")


Meiner Meinung nach müßte die "TTileEngine-Create" so aussehen:
BlitzMax: [AUSKLAPPEN]
	'Constructor
Method Create:TTileEngine(windowX:Int, windowY:Int)
Local constructor:TTileEngine = New TTileEngine

Print "New TTileEngine created"
constructor.windowX = windowX
constructor.windowY = windowY

Return constructor
End Method



das gleiche dann auch bei "TTileLayer Method Create":
BlitzMax: [AUSKLAPPEN]
Type TTileLayer
Field name:String

'Constructor
Method Create:TTileLayer(name:String)
Local constructor:TTileLayer = New TTileLayer

Print "New TTileLayer created: " + name
constructor.name = name

Return constructor
End Method


Die Namensgleichheit bei den zu übergebenden Parametern und dem Type selbst kann übrigens zu Problemen führen. Besser so:
BlitzMax: [AUSKLAPPEN]
	Method Create:TTileLayer(N:String)
Self.name = N
End Method


Dann ginge es nämlich auch so:
BlitzMax: [AUSKLAPPEN]
SuperStrict
Local tE:TTileEngine = New TTileEngine.Create(150, 150)
Print "X=" + te.windowX

tE.newLayer("Test Layer1")
tE.newLayer("Test Layer2")
tE.newLayer("Test Layer3")

For Local L:TTileLayer = EachIn tE.Layer
Print "Name=" + L.name
Next

Print "exit"



Type TTileEngine

Field windowX:Int
Field windowY:Int

Field Layer:TList = New TList


'Constructor
Method Create:TTileEngine(X:Int, Y:Int)
windowX =X
windowY =Y
Return Self
End Method


Method newLayer(name:String)
Local lay:TTileLayer = New TTileLayer.Create(name)
Self.Layer.AddLast(lay)
End Method

End Type



Type TTileLayer
Field name:String

'Constructor
Method Create:TTileLayer(N:String)
name = N
Return Self
End Method

End Type



und so auch:

BlitzMax: [AUSKLAPPEN]
SuperStrict
Local tE:TTileEngine = New TTileEngine
tE.Create(150, 150)
Print "X=" + te.windowX

tE.newLayer("Test Layer1")
tE.newLayer("Test Layer2")
tE.newLayer("Test Layer3")

For Local L:TTileLayer = EachIn tE.Layer
Print "Name=" + L.name
Next

Print "exit"



Type TTileEngine

Field windowX:Int
Field windowY:Int

Field Layer:TList = New TList


'Constructor
Method Create:TTileEngine(X:Int, Y:Int)
windowX =X
windowY =Y
End Method


Method newLayer(name:String)
Local lay:TTileLayer = New TTileLayer
lay.Create(name)
Layer.AddLast(lay)
End Method

End Type



Type TTileLayer
Field name:String

'Constructor
Method Create:TTileLayer(N:String)
name = N
End Method

End Type
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
  • Zuletzt bearbeitet von Midimaster am Di, Jan 26, 2016 9:45, insgesamt einmal bearbeitet
 

Schrolli

BeitragDi, Jan 26, 2016 9:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke, das wars tatsächlich...

Was ich aber nicht ganz verstehe - normalerweise nutzt man self ja, um sich selbst die werte zuzuweisen. nach dem "new TTileEngine" wird ja ein neues Objekt erstellt, wieso kann er in diesem Fall die Werte nicht per self an sich selbst übergeben?

Grüße Basti

Midimaster

BeitragDi, Jan 26, 2016 9:48
Antworten mit Zitat
Benutzer-Profile anzeigen
ich habe meinen Text oben gerade nochmal um genau dieses Thema ergänzt, da hattest Du aber schon in der Zwischenzeit schnell geantwortet.... Schau Dir das oben jetzt bitte nochmal an.
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
 

Schrolli

BeitragDi, Jan 26, 2016 10:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Ahhh jetzt versteh ich das glaube ich...

Das mit den gleichen Namen habe ich mir mal so angewöhnt, da man mir sagte es sei nicht unbedingt schlechter Code Stil, wenn das Zeug ordentlich und zuordenbar heißt. Auf alle Variablen innerhalb der Klasse wird dann strikt per self zugegriffen, dann kann das auch nicht zu Verwechslungen kommen.

Habs jetzt in Anlehnung an dein Beispiel so gelöst, läuft super
BlitzBasic: [AUSKLAPPEN]

Method newLayer(name:String)
Self.Layer.AddLast(New TTileLayer.Create(name) )
End Method

...

Type TTileLayer
Field name:String

'Constructor
Method Create:TTileLayer(name:String)
Print "New TTileLayer created: " + name
Self.name = name
Return Self
End Method

End Type



Edit:
Kann ich in der Liste auf einzelne Elemente eigentlich irgendwie per ID zugreifen, ähnlich wie bei nem Array?
Oder gibt es einen anderen Datentyp der so etwas gut beherrscht? Brauche im Prinzip etwas, wie ein Array, dessen Größe ich aber variabel zur Laufzeit verändern/vergrößen kann.

Midimaster

BeitragDi, Jan 26, 2016 11:05
Antworten mit Zitat
Benutzer-Profile anzeigen
ja, ich brauch das oft für meine Spiele.

z.b. so:

BlitzMax: [AUSKLAPPEN]
Local tE:TTileEngine = New TTileEngine
tE.Create(150, 150)
Print "X=" + te.windowX

tE.newLayer("Test Layer1",1)
tE.newLayer("Test Layer2",5)
tE.newLayer("Test Layer3",3)

For Local L:TTileLayer = EachIn tE.Layer
Print "alle... Name=" + L.name
Next

Print "Suche Element 5... Name=" + tE.Element(5).name
Print "exit"
End

Type TTileEngine
.....
Method newLayer(name:String,Nr:Int)
Self.Layer.AddLast New TTileLayer.Create(name,Nr)
End Method

Method Element:TTileLayer(_Nr:Int)
For Local loc:TTileLayer= EachIn Layer
If loc.Nr=_Nr
Return loc
EndIf
Next
Return Null
End Method
End Type



Type TTileLayer
Field name:String
Field Nr:Int

Method Create:TTileLayer(Name:String, Nr:Int)
Self.Name = Name
Self.Nr = Nr
Return Self
End Method
End Type
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe

Thunder

BeitragMi, Jan 27, 2016 1:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Schrolli hat Folgendes geschrieben:
Kann ich in der Liste auf einzelne Elemente eigentlich irgendwie per ID zugreifen, ähnlich wie bei nem Array?
Oder gibt es einen anderen Datentyp der so etwas gut beherrscht? Brauche im Prinzip etwas, wie ein Array, dessen Größe ich aber variabel zur Laufzeit verändern/vergrößen kann.


Listen sind sehr sehr schlecht in Zugriffen per Index. Die Performance wird sofort wegbrechen, weil dein Programm anfängt wild irgendwelche Adressen aus dem Speicher zu laden.

Wenn du hauptsächlich Elemente hinzufügst und sie immer nur auf einmal löscht, dann verwende ein Array.
Beispiel:

BlitzMax: [AUSKLAPPEN]
Type TTileLayer
Field name:String
End Type

Local array:TTileLayer[] = []

' neues Element einfügen
array :+ [New TTileLayer]

Local t:TTileLayer = New TTileLayer
t.name = "hallo"

array :+ [t]

' Array Länge
Print "length: "+array.length

' Index zugriff
Print "array[0]: "+array[0].name
Print "array[1]: "+array[1].name

' Alle Elemente löschen
array = []

' Einzelne Elemente löschen ist möglich, aber nicht
' besonders elegant (ungetestet!)
' bsp. drittes Element löschen:

array = array[..2] + array[3..]


Siehe auch Slicing in der BlitzMax Doku. Die letzte operation verwendet Slices. Das bedeutet, dass man einen Teil des Arrays kopiert ( array[..2] ist eine Kopie von array, wo nur die ersten beiden Elemente enthalten sind).
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

Midimaster

BeitragMi, Jan 27, 2016 10:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Wobei das mit dem "Performance-Einbruch relativ ist. Wenn Du einen Type mit 100 Layern hättest und darin ein Element auf die von mir beschriebene Index-Suche suchst, dann dauert das durchschnittlich 0.009 msec. Das heißt, selbst wenn so ein Suche 100x innerhalb eines FLIPs vorkommt verlierst du nur insgesamt 1msec von deinen 16 zur Verfügung stehenden. Meist liegt der Performance Ärger wo anders, (z.b. bei der zu erstellenden Grafik)

BlitzMax: [AUSKLAPPEN]
Global SuchName$, Zeit#
Local tE:TTileEngine = New TTileEngine
tE.Create(150, 150)

' Herstellen von einem Type mit 100 Layern,, der 50. ist der später gesuchte...
For Local i%=0 To 50
tE.newLayer("Test Layer1",1)
Next
tE.newLayer("Test Layer2",5)
For i=0 To 50
tE.newLayer("Test Layer3",3)
Next
Print
Print
'Test: Der Layer mit dem Index "5" wird gesucht
Zeit=MilliSecs()
For i%=0 To 100
SuchName=tE.Element(5).name
Next
Zeit=MilliSecs()-Zeit

Print "Test: Suche nach Element 5... Zeit=" + Zeit/100 + "msec"
Print
Print


Print "exit"
End

Type TTileEngine

Field Layer:TList = New TList

Method Create:TTileEngine(X:Int, Y:Int)
Return Self
End Method


Method newLayer(name:String,Nr:Int)
Self.Layer.AddLast New TTileLayer.Create(name,Nr)
End Method


Method Element:TTileLayer(_Nr:Int)
For Local loc:TTileLayer= EachIn Layer
If loc.Nr=_Nr
Return loc
EndIf
Next
Return Null
End Method
End Type



Type TTileLayer
Field name:String
Field Nr:Int

Method Create:TTileLayer(Name:String, Nr:Int)
Self.Name = Name
Self.Nr = Nr
Return Self
End Method
End Type

Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe
 

CO2

ehemals "SirMO"

BeitragMi, Jan 27, 2016 15:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Was sich bei sowas auch anbietet wäre eine Map. Eine Map ist eine Sammlung von Key-Value-Paaren. Der Vorteil von Maps ist, dass sie sehr schnell sind (nicht so schnell wie Arrays, aber schneller als Listen durchsuchen), da sie die enthaltenen Key-Value-Paare hashen (Frag' mich nicht, wie das genau funktioniert, ich weiß nur, dass es dadurch schneller wird, nach einem Key zu suchen Embarassed)
Folgendes simples Beispiel eines Association-Types BlitzMax: [AUSKLAPPEN]
Type TAssoc
Field Data:TMap

Function Create:TAssoc()
Local RetVal:TAssoc = New TAssoc
RetVal.Data = CreateMap()
Return RetVal
End Function

Method Add(Key:String, Val:Object)
If (Key = Null Or Val = Null) Then Return
If (MapContains(Self.Data, Key)) Then Return

MapInsert(Self.Data, Key, Val)
End Method

Method Get:TObject(Key:String)
Return MapValueForKey(Self.Data, Key)
End Method
End Type


Dies wäre ein allgemeiner Association-Type, den du natürlich noch anpassen kannst, indem du in der Methode Add() kein Object, sondern deinen Datentyp erwartest; Selbiges gilt für Get(), bei der du kein Object, sondern deinen Datentyp zurückgibst (du musst dabei jedoch den Return von MapValueForKey() in den Ziel-Datentyp casten).

In deinem Beispiel würde der obige Type die Liste ersetzen, deine Layer fügst du dann über TAssoc.Add() hinzu und rufst sie via TAssoc.Get() wieder ab.

P.S.: Durchiterien durch die Map tust du mit MapValues() oder MapKeys().
mfG, CO²

Sprachen: BlitzMax, C, C++, C#, Java
Hardware: Windows 7 Ultimate 64-Bit, AMX FX-6350 (6x3,9 GHz), 32 GB RAM, Nvidia GeForce GTX 750 Ti

Thunder

BeitragDo, Jan 28, 2016 16:15
Antworten mit Zitat
Benutzer-Profile anzeigen
Okay, jetzt wird da schon viel durcheinander geschmissen (Schrolli hat ja nicht ganz genau gesagt was er möchte).

Wenn du einen Container möchtest, bei dem du die Elemente mit Index ansprechen kannst, wobei der Index von 0 bis (Anzahl der Elemente minus 1) geht -> das ist ein Array.


Wenn du einen Container möchtest, bei dem du einen Key hast, und über den auf die Elemente zugreifen willst (z.B. Elemente = Mitarbeiter-Klassen und Key = Nachname des Mitarbeiters) -> das ist eine Map oder auch Hashtable.
Man kann eine Map durchaus auch verwenden, wenn der Key ein Int ist - das ist aber nur sinnvoll, wenn die Keys <> 0, 1, 2, 3 ... sind. Denn dann sind wir wieder beim Array.

Eine Map ist übrigens normalerweise ein Array aus LinkedLists (BlitzMax' TMap scheint aber auf den ersten Blick irgendwas mit Rot-Schwarz-Bäumen zu machen - dafuq? weiß jemand was genaueres?)
Problem von BlitzMax-Map: Key muss ein Object sein, d.h. du kannst Int nur als Key verwenden, wenn du dir eine Dummy-Klasse baust, die ein Int-Field hat.


Last and least, die Linked List. Sie punktet in der Theorie mit schnellem Einfügen und Entfernen. Vollständig über eine Linked List zu iterieren ist auch (in der Theorie) genau so effizient wie bei einem Array.

Caches und langsame Hauptspeicher machen diese schöne Theorie aber kaputt und wenn du genügend viele Elemente hast (aber nicht zu viele), wird das Array schneller als die Linked List (in allen Belangen!). Das habe ich gerade mit BlitzMax gebenchmarkt.

Wenn du wirklich wirklich viele Elemente hast (100e Millionen, Milliarden), dreht sich das wieder um (so weit geht mein Graph nicht).
Ich hab mal geordnetes Einfügen von zufälligen Zahlen in Linked List bzw Array geplottet:
user posted image

Das Problem ist: Index basierter Zugriff auf eine Linked List ist verdammt langsam und zwar immer (wirkt sich aber auch erst mit vielen Elementen aus (weswegen Midimasters 0.009 ms noch ganz harmlos klingen).
Ein Plot (zufälliger zugriff auf Elemente einer Liste/eines Arrays):
user posted image

BlitzMax bräuchte von Haus aus eine ArrayList klasse (ähnlich Java), die das Managen von Arrays einfacher macht.

Errata:

BlitzMax: [AUSKLAPPEN]
' Ich habe im vorherigen Beitrag behauptet man dürfe folgendes:
array = []
'Das ist aber Python syntax und in BlitzMax nicht möglich. Es sollte
array = Null
' sein


PS: Implementierung des Benchmarks:
BlitzMax: [AUSKLAPPEN]
Strict
Framework brl.standardio
Import brl.linkedlist
Import brl.random

Type Foo
Field x
Method New()
x = Rand(0, 100000000)
EndMethod
EndType

Function array_insert(arr:Foo[] Var, n:Foo)
If arr.length = 0 Then
arr = [n]
Return
ElseIf arr.length > 0 And arr[0].x > n.x Then
arr = [n] + arr
Return
EndIf
For Local i = 1 Until arr.length
If arr[i-1].x < n.x And arr[i].x >= n.x Then
arr = arr[..i] + [n] + arr[i..]
Return
EndIf
Next
arr :+ [n]
EndFunction

Function list_insert(list:TList, n:Foo)
If list.isempty() Then
list.addlast n
Return
EndIf

Local f : Foo = Foo( list.first() )
If list.count() > 0 And f.x > n.x Then
list.addfirst n
Return
EndIf

Local last = f.x
Local c:TLink = list.firstlink()

While c <> Null
If last < n.x And Foo(c.value()).x >= n.x Then
list.insertbeforelink n, c
Return
EndIf
c = c.nextlink()
Wend

list.addlast n
EndFunction

Const ACCESSES = 10000000
Const SEED = 1337

Function time_list_insert(list:TList, num)
SeedRnd SEED

Local t = MilliSecs()
For Local i = 1 To num
list_insert list, New Foo
Next
t = MilliSecs() - t

Return t
EndFunction
Function time_array_insert(array:Foo[] Var, num)
SeedRnd SEED

Local t = MilliSecs()
For Local i = 1 To num
array_insert array, New Foo
Next
t = MilliSecs() - t

Return t
EndFunction

Function time_list_randomaccess(list:TList, num)
SeedRnd SEED

Local randmax = list.count() - 1

Local t = MilliSecs()
For Local i = 1 To num
Local index = Rand(0, randmax)
Foo(list.valueatindex(index)).x :+ 1
Next
t = MilliSecs() - t

Return t
EndFunction
Function time_array_randomaccess(array:Foo[] Var, num)
SeedRnd SEED

Local randmax = array.length - 1

Local t = MilliSecs()
For Local i = 1 To num
Local index = Rand(0, randmax)
array[index].x :+ 1
Next
t = MilliSecs() - t

Return t
EndFunction

Function verify_array(array:Foo[] Var)
If array.length = 0 Then Return True
Local x = array[0].x
For Local i = 1 Until array.length
If x > array[i].x Then Return False
x = array[i].x
Next
Return True
EndFunction

Function verify_list(list:TList)
If list.isempty() Then Return True
Local fl:TLink = list.firstlink()
Local x = Foo(fl.value()).x
fl = fl.nextlink()
While fl <> Null
Local f:Foo = Foo(fl.value())
If x > f.x Then Return False
x = f.x
fl = fl.nextlink()
Wend
Return True
EndFunction


Local array:Foo[] = Null
Local list:TList = New TList

Const NUM_MIN = 1000
Const NUM_MAX = 72000
Const NUM_STEP = 1000

If Input("insertion test? [Y/n] ").tolower() <> "n" Then

Print "INSERTION OF RANDOM NUMBERS IN ORDER"
Print "Insertions ~tTime array (ms) ~tTime list (ms)"
For Local num = NUM_MIN To NUM_MAX Step NUM_STEP
Local t_array = time_array_insert(array, num)
Local t_list = time_list_insert(list, num)
Print num+" ~t"+t_array+" ~t"+t_list
If Not verify_array(array) Then Print "array wrong"
array = Null
If Not verify_list(list) Then Print "array wrong"
list.clear
Next

EndIf

If Input("access test? [Y/n]").tolower() <> "n" Then

Local elements = (NUM_MAX+NUM_MIN)/2

For Local i = 1 To elements
array :+ [New Foo]
list.addlast New Foo
Next

Print "RANDOM ACCESS ON SEQUENCE WITH "+elements+ " ELEMENTS"
Print "Accesses ~tTime array (ms) ~tTime list (ms)"
For Local num = NUM_MIN To NUM_MAX Step NUM_STEP

Local t_array = time_array_randomaccess(array, num)
Local t_list = time_list_randomaccess(list, num)

Print num+" ~t"+t_array+" ~t"+t_list
Next

EndIf
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

DAK

BeitragSa, Jan 30, 2016 16:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Jup, das Ganze mal noch von der Theorie her:

Array
Ein Speicherblock einer bestimmten Größe wird beim Erstellen vorreserviert. Der Block bleibt dabei immer gleich groß, vergrößern oder verkleinern geht nicht. Will man sowas tun, dann muss ein neuer Block in der neuen Größe reserviert werden, und alles vom alten Array in das neue Array kopiert werden. Dadurch, das der Speicher aber eine fixe, vorherbestimmte Größe hat, kann man auf einzelne Objekte direkt zugreifen (indizieren), ohne Performance-Verlust, egal wie groß das Array ist.
Also:
-Größe von Anfang reserviert
-Größe ändern kostet viel ( O(n) = Zeit abhängig von der Größe des Arrays)
-Direkter Zugriff auf einzelne Objekte ist irre schnell ( O(1) = konstante Zugriffszeit, egal wie groß das Array ist)
-Somit ist auch iterieren (die Elemente der Reihe nach durchgehen) gleich flott ( O(1) )

Linked List
Hierbei wird für jedes Element der benötigte Speicherbereich neu reserviert. Jedes Element hat dabei einen Verweis (Link) auf das nächste (und je nach Implementierung auch das vorige) Element in der Liste. Dadurch ist neue Elemente hinzufügen oder Elemente löschen sehr schnell. Die Elemente iterieren ist auch sehr schnell, da jedes Element einen Link auf das nächste Element besitzt. Objekte indizieren ist aber sehr langsam, da man sich durch die ganze Liste Element für Element durchhanteln muss, um an den richtigen Punkt zu kommen.
Also:
-Größe dynamisch
-Größe ändern ist billig ( O(1) )
-Indizieren braucht sehr lange ( O(n) = Zugriffszeit abhängig von der Anzahl der Elemente in der Liste)
-Iterieren geht aber flott ( O(1) )

Array List
Die Array List ist in BMax nicht von haus aus drinnen, ist aber sehr leicht zu implementieren. Diese ist im Grunde ein Array, das aber größer als benötigt initialisiert wird. Z.B. initialisiert man das Array mit 32 Plätzen, die am Anfang auf Null gesetzt sind. Dazu hat die Array List einen Zähler, wie voll sie ist. Wenn man ein Element hinzufügt, dann kommt es einfach an das erste freie Feld und der Zähler geht um eins hoch. Ist das Array voll, dann wird es, wie unter Array beschrieben auf die doppelte Größe erhöht und das Spiel geht weiter. Wird ein Element gelöscht, dann müssen alle nachfolgenden Elemente zurückverschoben werden, das kostet also. Dafür ist indizieren wieder so schnell wie bei Array.
Also:
-Größe halbdynamisch, mehr Speicherverbrauch als bei den Anderen
-Elemente hinzufügen ist billig ( O(1) ) außer beim Resizen ( O(n) ), das aber selten vorkommt
-Löschen ist eher teuer ( O(n) )
-Indizieren und iterieren geht sehr flott ( O(1) )

Map
Ich gehe hier mal von HashMaps aus, da das die üblichste Implementierung ist. Hashmaps sind dazu da, das man schnell von einem Objekt auf ein anderes kommt, z.B. vom Namen eines Spielers zum Objekt, das dessen Raumschiff repräsentiert. Von der Datenspeicherung her, besteht eine HashMap aus einem Array mit Listen drinnen. Jede dieser Listen nennt man Buckets. Wird ein Objekt hinzugefügt, dann wird aus dem Objekt ein Hash erstellt (Hash=Identifikationszahl, die aus dem Objekt mathematisch errechnet wird). Dieser Hash bestimmt, in welchen Bucket das Objekt kommt. In diesem Bucket werden alle Objekte mit dem gleichen Hash gespeichert. Beim Auslesen wird das gleiche gemacht, und dann der Bucket nach dem Objekt mit dem gleichen Key gesucht. Das heißt, hier variieren die Zugriffszeiten, sind aber üblicherweise schneller als eine LinkedList, aber langsamer als ein Array oder eine ArrayList. Dafür können beliebige Werte als Key verwendet werden, nicht nur fortlaufende Zahlen.
Also:
-Größe dynamisch, aber da die Keys mitgespeichert werden müssen, schon eher groß
-Elemente hinzufügen, löschen und indizieren ist generell eher billig ( O(1) ), kann aber im Extremfall auch etwas langsamer sein ( O(n) )
-Iterieren geht eigentlich nicht. Dafür muss man sich z.B. eine Liste aller Keys machen, und die iterieren und jeweils den Wert aus der Map raussuchen.
-Im Gegensatz zu den anderen Strukturen gibt es in der HashMap auch eine Reihenfolge der Werte. Eine Map sortieren geht z.B. nicht.
Gewinner der 6. und der 68. BlitzCodeCompo

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group