Element von einer LinkedList in eine andere schieben

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
jacdelad
Beiträge: 404
Registriert: 03.02.2021 13:39
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...
Guten Morgen, das ist ein schöner Tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3 TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

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
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: 636
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: 636
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