[Multi Plateforme] Listes chainées dynamiques.

Partagez votre expérience de PureBasic avec les autres utilisateurs.
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

[Multi Plateforme] Listes chainées dynamiques.

Message par poshu »

Qui n'a jamais voulu faire rentrer une liste chainée dans une structure? Ou créer dynamiquement des listes chainées dans son programme?
En tous cas, moi j'en ai souvent eu besoin, alors voilà une solution:

Code : Tout sélectionner

#SizeOfInteger = SizeOf(Integer)

Structure Dynamic_Linked_List
  *ptr.i
  number.i
EndStructure

Procedure DLLCountElement(*this.Dynamic_Linked_List)
	ProcedureReturn *this\number
EndProcedure

Procedure DLLSetElement(*this.Dynamic_Linked_List,number.i, *Element)
	If number > *this\number
	  *this\number = number
	  *this\ptr = ReAllocateMemory(*this\ptr, number * #SizeOfInteger)
	EndIf
	PokeI(*this\ptr + (number-1) * #SizeOfInteger, *Element)
EndProcedure

Procedure DLLAddElement(*this.Dynamic_Linked_List,*Element)
	DLLSetElement(*this,*this\number+1, *Element)
	ProcedureReturn *this\number
EndProcedure

Procedure DLLFreeElement(*this.Dynamic_Linked_List,number.i)
	If *this\number = 1
	  *this\number = 0
	  FreeMemory(PeekI(*this\ptr))
	Else
  	If number <= *this\number
	    FreeMemory(PeekI(*this\ptr + (number-1) * #SizeOfInteger))
      CopyMemory(*this\ptr + #SizeOfInteger*number,  *this\ptr + #SizeOfInteger*(number - 1), #SizeOfInteger*(*this\number-number))
    	*this\number - 1
    	*this\ptr = ReAllocateMemory(*this\ptr, *this\number * #SizeOfInteger)
  	EndIf
	EndIf
EndProcedure

Procedure DLLGetElement(*this.Dynamic_Linked_List,number.i)
	If number <= *this\number
	  ProcedureReturn PeekI(*this\ptr + (number-1) * #SizeOfInteger)
	Else
	  ProcedureReturn 0
	EndIf
EndProcedure

Procedure DLLRemoveAll(*this.Dynamic_Linked_List)
  Protected loop
  For loop = 1 To *this\number
    DLLFreeElement(*this,1)
  Next loop
  *this\number  = 0
  *this\ptr = ReAllocateMemory(*this\ptr, 1)
EndProcedure

Procedure DLLFreeList(*this.Dynamic_Linked_List)
  Protected loop
  For loop = 1 To *this\number
     DLLFreeElement(*this,1)
  Next loop
  FreeMemory(*this\ptr)
EndProcedure

Procedure DLLNewlist(*this.Dynamic_Linked_List)
  *this\ptr = AllocateMemory(1)
EndProcedure
Bon, alors niveau utilisation, voici un exemple:

Code : Tout sélectionner

DLLNewlist(Test.Dynamic_Linked_List)

DLLAddElement(Test,AllocateMemory(SizeOf(byte)))

DLLAddElement(Test,AllocateMemory(SizeOf(byte)))

DLLAddElement(Test,AllocateMemory(SizeOf(byte)))

PokeB(DLLGetElement(Test,3),12)

DLLFreeElement(Test,2)

Debug PeekB(DLLGetElement(Test,2))

Debug DLLCountElement(Test)

DLLFreeElement(Test,2)

Debug DLLCountElement(Test)

DLLFreeList(Test)
Petite explication: la liste ne fait que mémoriser des pointeurs mémoires. Ainsi, quand on ajoute un élément, on crée une zone mémoire (peut importe la taille) et on ajoute son adresse dans la liste.
On peut par la suite récupérer le pointeur et y lire ou écrire via des peek et des poke.
L'avantage: on peut faire des listes où chaque élément est d'un type différent (ceci dit, c'est pas conseillé, par ce que pour naviguer dedans après, ca peut être du sport); et surtout on peut faire quelque chose comme ca:

Code : Tout sélectionner

Structure test
  blabla.s
  blibli.l
  Listdynamique.Dynamic_Linked_List
EndStructure

Truc.test

DLLNewlist(truc\Listdynamique)
Et donc imbriquer des listes dans d'autres listes, ou dans des tableau (ou n'importe quoi d'autre en fait).


L'inconvénient: Ca peut provoquer des memory leaks, j'ai pas vraiment checké la lib de ce coté là; mais je fais attention quand je l'utilise, faites pareil :þ.

Coté vitesse d'utilisation, y'a surement de l'optimisation à faire, mais le résultat actuel est déjà relativement rapide.
Dernière modification par poshu le lun. 29/mars/2010 16:43, modifié 2 fois.
cha0s
Messages : 681
Inscription : sam. 05/mars/2005 16:09

Re: [Multi Plateforme] Listes chainées dynamiques.

Message par cha0s »

ne sous estime pas PB et son préprocesseur mon cher poshu :p

Code : Tout sélectionner

#SizeOfInteger = SizeOf(Integer)
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Re: [Multi Plateforme] Listes chainées dynamiques.

Message par poshu »

ah, il le fait comme un grand? J'avais un doute, s'pas un compilerif qui change grand chose de toutes façons.
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Re: [Multi Plateforme] Listes chainées dynamiques.

Message par poshu »

Petite correction, vraiment minime, pour que le code compile en EnableExplicit, et puis j'ai pris en compte la remarque de chaos pour gagner quelques lignes de code ^^;
Répondre