Element von einer LinkedList in eine andere schieben

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
jacdelad
Beiträge: 348
Registriert: 03.02.2021 13:39
Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
Wohnort: Riesa
Kontaktdaten:

Element von einer LinkedList in eine andere schieben

Beitrag von jacdelad »

Hallo,
ich hab leider nichts zufriedenstellendes gefunden: Wie kann ich ein Element von einer LimkedList in eine andere schieben? Mit einfachen Variablen ist das natürlich einfach, wenn ich aber eine Struktur benutze muss ich alle Elemente der Struktur bearbeiten. Vielleicht geht das ja einfacher.

Edit: Ach verdammt, Rechtschreibfehler im Titel...
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8679
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Element von einer LinkedList in eine andere schieben

Beitrag von NicTheQuick »

jacdelad hat geschrieben:Edit: Ach verdammt, Rechtschreibfehler im Titel...
Jetzt nicht mehr :wink:

Zur Frage:
Ein effizientes Verschieben ist meines Wissens nicht ohne Hacks möglich. Und mit Hacks meine ich die inneren Datenstrukturen der eingebauten LinkedLists zu ändern.
Was dir aber helfen könnte ist vielleicht CopyStructure() bzw. die native Zuweisung von strukturierten Variablen:

Code: Alles auswählen

Structure myStructure
	i.i
	s.s
EndStructure

NewList a.myStructure()
NewList b.myStructure()

For i = 0 To 9
	If AddElement(a())
		a()\i = i
		a()\s = "Item " + i
	EndIf
	If AddElement(b())
		b()\i = i + 10
		b()\s = "Item " + Str(i + 10)
	EndIf
Next

Procedure MoveElementBetweenLists(List a.myStructure(), List b.myStructure())
	If AddElement(b())
		b() = a()
		DeleteElement(a())
	EndIf
EndProcedure

; Select first element in list a() to move before the first element of list b()
FirstElement(a())
ResetList(b())

MoveElementBetweenLists(a(), b())

Debug "a()"
ForEach a()
	Debug a()\s
Next

Debug "b()"
ForEach b()
	Debug b()\s
Next
Bild
ST4242
Beiträge: 42
Registriert: 29.10.2011 16:54

Re: Element von einer LinkedList in eine andere schieben

Beitrag von ST4242 »

Hallo,

eine möglichkeit ist die Listen mit Zeigern zu erzeugen, dann muß nur der Zeiger in die andere Liste gegeben werden.

Allerdings sollte man bei dieser Lösung gut im Umgang mit Speicherbereichen sein, da am Ende der Speicher für jedes Element auch immer manuell freigeben werden muß.

Weiterhin ist so möglich das in beiden Listen auf die gleichen Daten verwiesen wird.

Wie gesagt ist nur für etwas erfahrene Programmierer

Gruß

Code: Alles auswählen

Structure s1
  a.i
  b.i
  s.s
EndStructure


NewList *l1.s1()
NewList *l2.s1()

For i =1 To 20
  AddElement(*l1()) 
  ; *l1()=AllocateStructure(s1)
  *l1()=AllocateMemory(SizeOf(s1))
 *l1()\a=i
 *l1()\b=i+100
 *l1()\s  ="!text "+Str(i)
Next i

FirstElement(*l1())
SelectElement(*l1(),4)
AddElement(*l2())

*l2()=*l1()
DeleteElement(*l1())
Debug *l2()\s

Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Element von einer LinkedList in eine andere schieben

Beitrag von helpy »

Eine andere etwas umständliche Möglichkeit das aktuelle Element von Liste A ans Ende von Liste B zu verschieben, wäre die Verwendung von MoveElement, SplitList und MergeList:

Code: Alles auswählen

EnableExplicit

Structure tTest
	Name.s
	Value.i
	ValueString.s
EndStructure

Procedure DebugList(List dl.tTest(), ListName.s)
	Debug ""
	Debug ListName
	Debug "-----"
	ForEach dl()
		Debug dl()\Name + " / " + Str(dl()\Value) + " / " + dl()\ValueString
	Next
EndProcedure

Procedure MoveCurrentElement(List src.tTest(), List target.tTest())
	Protected NewList tmp.tTest()
	MoveElement(src(), #PB_List_Last)
	SplitList(src(), tmp(), #False)
	MergeLists(tmp(), target(), #PB_List_Last)
EndProcedure

NewList listA.tTest()
NewList listB.tTest()
Define i, j

For i = 1 To 10
	AddElement(listA())
	With listA()
		\Name = "Element " + Str(i)
		\Value = Random(1000000,1)
		\ValueString = Str(\Value)
	EndWith
Next i

DebugList(listA(), "Liste A")
DebugList(listB(), "Liste B")

For i = 10 To 1 Step -1
	j = Random(i,1)
	SelectElement(listA(), j-1)
	MoveCurrentElement(listA(), listB())
Next i

DebugList(listA(), "Liste A")
DebugList(listB(), "Liste B")
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
helpy
Beiträge: 635
Registriert: 29.08.2004 13:29

Re: Element von einer LinkedList in eine andere schieben

Beitrag von helpy »

Ich habe mal einen Test gemacht und wollte wissen, wie schnell Elemente auf diese etwas umständliche Art verschoben werden. Test mit etwas geänderter Methode:

Code: Alles auswählen

EnableExplicit

Structure tTest
	Name.s
	Value.i
	ValueString.s
EndStructure

Procedure MoveCurrentElement(List src.tTest(), List target.tTest())
	Static NewList tmp.tTest()
	MoveElement(src(), #PB_List_Last)
	SplitList(src(), tmp())
	MergeLists(tmp(), target())
EndProcedure

NewList listA.tTest()
NewList listB.tTest()
Define i, j

#ListSize = 1000000

For i = 1 To #ListSize
	AddElement(listA())
	With listA()
		\Name = "Element " + Str(i)
		\Value = Random(10000000,1)
		\ValueString = Str(\Value) 
	EndWith
Next i

MessageRequester("Start moving elements!", 
                 "Listsize of listA: " + Str(ListSize(listA())) + #CRLF$ + 
                 "Listsize of listB: " + Str(ListSize(listB())) + #CRLF$)
Define start = ElapsedMilliseconds()
LastElement(listA())
For i = #ListSize To 1 Step -1
	MoveCurrentElement(listA(), listB())
Next i
Define ende = ElapsedMilliseconds()
MessageRequester("Move " + Str(#ListSize) + " elements!", 
                 "Moved all elements to other list in " + Str(ende-start) + " ms!" + #CRLF$ +
                 "Listsize of listA: " + Str(ListSize(listA())) + #CRLF$ + 
                 "Listsize of listB: " + Str(ListSize(listB())) + #CRLF$)
(1) Auf meinem Notebook (Core i3, 2,3 GHz) werden 1.000.000 Elemente innerhalb von 41ms verschoben.
Die Methode mit dem "Static NewList tmp.tTest()" sollte nicht in Threads verwendet werden.
(2) Mit "Protected NewList tmp.tTest()" braucht die Methode bereits über 1,7s.
(3) Alternativ mit "Threaded NewList tmp.tTest()" (definiert außerhalb der Methode) braucht es bei mir 56ms.

Methoden 1 + 3 sind aber gar nicht so langsam ;-)
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Antworten