SelectElement() vs PreviousElement()

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
THEEX
Beiträge: 804
Registriert: 07.09.2004 03:13

SelectElement() vs PreviousElement()

Beitrag von THEEX »

Ich schreib grad an einem Programm, bei dem ich Listen recht häufig durchsuche und Teilweise rückwärts durchlaufen lasse. Anfänglich hab ich aus verschiedenen Gründen die Elemente meist mit SelectElement() angegeben. Heut hab ich schließlich PreviousElement() bei weiteren Routinen benutzt. Zwar ist es für mein Programm kaum relevant, was nun schneller funktioniert, jedoch kam ich dadurch auf die Idee, mal zu schauen, was nun schneller ist. Ich hätte nicht gedacht, daß SelectElement() so extrem langsamer funktioniert, bei größeren Listen sollte man das aber unbedingt wissen. Hier ein Speedvergleich, wobei man vielleicht beachten sollte, daß es bei alten Rechnern eventuell ewig dauern kann und man vielleicht den Endwert der For:Next-Schleife runter setzen sollte... ich selbst hab 'nen Doppelprozi mit 2100 mHz.

Code: Alles auswählen

NewList Liste()

Debug "Liste füllen"
Start = ElapsedMilliseconds()
For a = 0 To 100000
  AddElement(Liste())
Next
Debug Str(ElapsedMilliseconds() - Start) + " ms"
Debug "----------------------------"

Debug "Mit PreviousElement()"
pos = ListenEnde
Start = ElapsedMilliseconds()
While ListIndex(Liste()) <> 0
  PreviousElement(Liste())
  pos - 1 
Wend
Debug Str(ElapsedMilliseconds() - Start) + " ms"
Debug "----------------------------"

ListenEnde = CountList(Liste()) - 1
Debug "Mit SelectElement()"
pos = ListenEnde
Start = ElapsedMilliseconds()
While pos <> 0
  SelectElement(Liste(), pos)
  pos - 1
Wend
Debug Str(ElapsedMilliseconds() - Start) + " ms"
Debug "----------------------------"
16 ms (PreviousElement()) vs 63250 ms (SelectElement())
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

was völlig logisch ist:
PB-Help SelectElement() hat geschrieben:Da LinkedLists keinen Index verwenden, wird allerdings zwangsweise bis zu der Zielposition jedes Element schrittweise angesprungen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Naja, nicht unbedingt:

Code: Alles auswählen

Structure PB_LinkedListData_Struc
  *FirstElement.PB_LinkedListElement_Struc ; FirstElement(LL()): = @LL()-8
  *LastElement.PB_LinkedListElement_Struc ; LastElement(LL()): = @LL()-8
  SizeofElement.l ; (Structure + *NextElement.l and *PrevElement.l (8 Byte))
  AmountofElements.l ; = CountList()
  NumberofCurrentElement.l ; = ListIndex() + 1 (with the normal PB 3.92 LL-Library NumberofCurrentElement.l is equal to the result of ListIndex(), with the new one from purebasic.com/beta its bigger by 1)
  StructureMap.l ; "the StructureMap is the address of the structure associated with the list, so if there is string in it they can be freed easily" by AlphaSND (explained at the end of the file)
  IsSetNumberofCurrentElement.l ; Is NumberofCurrentElement saving the correct value? (0=yes,other=no)
EndStructure

Structure PB_LinkedListElement_Struc
  *NextElement.l
  *PrevElement.l
  ;[...] Content
EndStructure

Structure PB_LinkedList_Struc
  *PB_LinkedListData.PB_LinkedListData_Struc
  *CurrentElement.PB_LinkedListElement_Struc
EndStructure

Global NewList Liste() 

DisableDebugger
Procedure SelectElement2(LinkedList(),Position)
  Protected *LL.PB_LinkedList_Struc
  MOV *LL, Eax ;LinkedList()
  
  LastElement = *LL\PB_LinkedListData\AmountofElements - 1
  
  WaytoLast = LastElement - Position
  If WaytoLast < 0 Or Position < 0
    ;invalid position
    ProcedureReturn #False
  EndIf
  WaytoFirst = Position
    
  If *LL\PB_LinkedListData\IsSetNumberofCurrentElement = 0 ;We know the index of the current element
    CurrentElement = *LL\PB_LinkedListData\NumberofCurrentElement - 1
    
    WaytoCurrent = Position - CurrentElement
    
    If AbsInt(WaytoCurrent) < WaytoLast And AbsInt(WaytoCurrent) < WaytoFirst ; The distance from the current element to element at 'position' is smaller than to the first or last element 
      While WaytoCurrent < 0 ;so we go back if WaytoCurrent < 0 ...
        PreviousElement(LinkedList())
        WaytoCurrent + 1
      Wend
      While WaytoCurrent > 0 ;or forward to reach 'position'
        NextElement(LinkedList())
        WaytoCurrent - 1
      Wend
    ElseIf WaytoLast < WaytoFirst
      LastElement(LinkedList())
      While WaytoLast
        PreviousElement(LinkedList())
        WaytoLast - 1
      Wend
    Else
      FirstElement(LinkedList())
      While WaytoFirst
        NextElement(LinkedList())
        WaytoFirst - 1
      Wend
    EndIf
  Else ; We dont know it :)
    If WaytoLast < WaytoFirst
      LastElement(LinkedList())
      While WaytoLast
        PreviousElement(LinkedList())
        WaytoLast - 1
      Wend
    Else
      FirstElement(LinkedList())
      While WaytoFirst
        NextElement(LinkedList())
        WaytoFirst - 1
      Wend
    EndIf
  EndIf
  ProcedureReturn @LinkedList()
EndProcedure
EnableDebugger

Debug "Liste füllen" 
Start = ElapsedMilliseconds() 
For a = 0 To 20000
  AddElement(Liste()) 
  Liste() = a
Next 
Debug Str(ElapsedMilliseconds() - Start) + " ms" 
Debug "----------------------------" 

Debug "Mit PreviousElement()" 
pos = ListenEnde 
Start = ElapsedMilliseconds() 
While ListIndex(Liste()) <> 0 
  PreviousElement(Liste()) 
  pos - 1 
Wend 
Debug Str(ElapsedMilliseconds() - Start) + " ms" 
Debug "----------------------------" 

ListenEnde = CountList(Liste()) - 1 
Debug "Mit SelectElement()" 
pos = ListenEnde 
Start = ElapsedMilliseconds() 
While pos <> 0 
  SelectElement(Liste(), pos) 
  pos - 1 
Wend 
Debug Str(ElapsedMilliseconds() - Start) + " ms" 
Debug "----------------------------"

ListenEnde = CountList(Liste()) - 1 
Debug "Mit SelectElement2()" 
pos = ListenEnde 
Start = ElapsedMilliseconds() 
While pos <> 0 
  SelectElement2(Liste(), pos)
  If ListIndex(Liste()) <> pos
    MessageRequester(Str(ListIndex(Liste())),Str(pos),16)
    End
  EndIf
  pos - 1 
Wend 
Debug Str(ElapsedMilliseconds() - Start) + " ms" 
Debug "----------------------------"
(Ja, ich hab Fred gerade gezeigt ;) )
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
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

Beitrag von NicTheQuick »

So wie Deeem2031 das macht, hab ich es mit meinen LinkedLists auch immer
gemacht und in meiner Datenbank hab ich auch sowas drin.
DeltaG
Beiträge: 112
Registriert: 10.09.2004 18:15

Beitrag von DeltaG »

Da fehlt ein 'h'!
Wußte gar nicht, daß PB Alkohol mag und sich deshalb bei obigem Pgm über das fehlende 'h' bei
If AbsInt(WaytoCurrent) < WaytoLast And AbsInt(WaytoCurrent) < WaytoFirst ; The distance from the current element to element at 'position' is smaller than to the first or last element
While WaytoCurrent < 0 ;so we go back if WaytoCurrent < 0 ...
beschwert. :lol:

Oder bedeutet 'AbsInt' hier was anderes? :wink:
Antworten