Structures séquentielles II - Représentation des listes Nathalie Junior Bouquet Février 2013 1 1.1 Listes itératives : Représentation contiguë (statique) Le type La liste est stockée dans un tableau (un vecteur) : la ième case contient le ième élément de la liste. Cette représentation limite donc la longueur de la liste qui ne peut dépasser la taille du tableau. Afin de ne prendre en compte que les cases du vecteurs contenant les éléments de la liste, il est nécessaire de connaître sa longueur. Donc la liste sera représentée par un couple < T ableau, Entier > : constantes LMax = 100 types /* déclaration du type t_element*/ t_vectLMaxElts = LMax t_element t_liste = enregistrement t_vectLMaxElts elts entier longueur fin enregistrement t_liste variables t_liste L.elts L.longueur 1.2 1.2.1 L 1 2 ... n e1 n e2 ... en ... LMax Implémentation des opérations De simples correspondances Type abstrait : Liste itérative Implémentation : type t_liste λ : Liste L : t_liste λ ← liste-vide L.longueur ← 0 longueur (λ) L.longueur ième(λ, k) L.elts[k] On remarque que la notion de place n’est pas présente ici. Celle-ci n’a pas d’équivalent directe dans cette implémentation 1 en langage Algo et n’est pas nécessaire à sa manipulation. 1. En C, par exemple, l’accès à la ième place de L peut être représenté par l’adresse mémoire de la ”case“. Ainsi, l’opération succ est représentée par la succession des cases du tableau en mémoire (il suffit d’incrémenter le pointeur). 1 Algorithmique Structures séquentielles Les listes – février 2013 1.2.2 Info-Sup Épita Des algorithmes L’accès au k ème élément d’une liste est immédiat. Par contre, pour l’insertion et la suppression, il faut déplacer tous les éléments de la place où s’effectue l’opération jusqu’à la fin de la liste pour reconstituer la structure. Les opérations présentées ici supposent de connaître le rang (donc la place dans le vecteur) de l’élément à supprimer ou insérer. Les versions vues en td commenceront par effectuer une recherche de cette place. L’opération supprimer opérations supprimer : Liste × Entier → Liste préconditions supprimer (λ, k) est-défini-ssi 1 ≤ k ≤ longueur(λ) axiomes λ ̸= liste-vide & 1 ≤ k ≤ longueur(λ) ⇒ longueur(supprimer(λ, k)) = longueur(λ) − 1 λ ̸= liste-vide & 1 ≤ k ≤ longueur(λ) & 1 ≤ i < k ⇒ ième(supprimer(λ, k), i) = ième(λ, i) λ ̸= liste-vide & 1 ≤ k ≤ longueur(λ) & k ≤ i ≤ longueur(λ) − 1 ⇒ ième(supprimer(λ, k), i) = ième(λ, i + 1) avec λ : Liste k, i : Entier L’algorithme que nous écrivons modifie directement la liste passée en paramètre. L’implémentation proposée ici est une fonction retournant un booléen indiquant si la suppression a réellement été effectuée. algorithme fonction supprimer : booleen parametres globaux t_liste L parametres locaux entier k variables entier i debut si (k<1) ou (k > L.longueur) alors /* le test L.longueur=0 est inutile ! */ retourne faux sinon pour i ← k jusqu’a L.longueur-1 faire L.elts[i] ← L.elts[i+1] fin pour L.longueur ← L.longueur - 1 retourne vrai fin si fin algorithme fonction supprimer Un peu de complexité : Si n est la longueur de la liste, une suppression demande au plus n − 1 affectations (suppression du premier élément = le pire des cas). L’opération insérer opérations insérer : Liste × Entier × Élément → Liste préconditions insérer(λ, k, e) est-défini-ssi 1 ≤ k ≤ longueur(λ) + 1 2 Algorithmique Structures séquentielles Les listes – février 2013 axiomes 1≤k 1≤k 1≤k 1≤k ≤ longueur(λ) + 1 ≤ longueur(λ) + 1 ≤ longueur(λ) + 1 ≤ longueur(λ) + 1 Info-Sup Épita ⇒ longueur(insérer(λ, k, e)) = longueur(λ) + 1 & 1 ≤ i < k ⇒ ième(insérer(λ, k, e), i) = ième(λ, i) & k = i ⇒ ième(insérer(λ, k, e), i) = e & k < i ≤ longueur(λ) + 1 ⇒ ième(insérer(λ, k, e), i) = ième(λ, i − 1) avec λ : Liste k, i : Entier e : Élément algorithme fonction inserer : booleen parametres globaux t_liste L parametres locaux entier k t_element e variables entier i debut si (L.longueur >= LMax) ou (k < 1) ou (k > L.longueur+1) alors retourne faux sinon pour i ← L.longueur jusqu’a k decroissant faire L.elts[i+1] ← L.elts[i] fin pour L.elts[k] ← e L.longueur ← L.longueur + 1 retourne vrai fin si fin algorithme fonction inserer L’utilisation de mémoire statique impose de tester que le résultat ne dépassera pas la taille du vecteur utilisé pour représenter la liste. Un peu de complexité : Si n est la longueur de la liste, une insertion demande au plus n+1 affectations (insertion à la première place = pire des cas) Remarques La représentation contiguë est bien adaptée aux listes itératives : accès et parcours sont très efficaces. Mais les suppressions et insertions sont coûteuses (à cause des déplacements). De plus, il est nécessaire de savoir majorer la taille des listes. Elle est par contre moins adaptée aux listes récursives : l’accès au premier élément est facile, mais les opérations cons et fin sont difficiles à représenter. Nous verrons, dans la section suivante, la représentation chaînée qui est bien plus adaptée aux listes récursives. 1.3 Extensions L’opération concaténer opérations concaténer : Liste × Liste → Liste axiomes longueur(concaténer(λ, λ′ )) = longueur(λ) + longueur(λ′ ) 1 ≤ i ≤ longueur(λ) ⇒ ième(concaténer(λ, λ′ ), i) = ième(λ, i) longueur(λ) + 1 ≤ i ≤ longueur(λ) + longueur(λ′ ) ⇒ ième(concaténer(λ, λ′ ), i) = ième(λ′ , i − longueur(λ)) 3 Algorithmique Structures séquentielles Les listes – février 2013 Info-Sup Épita avec λ, λ′ : Liste i : Entier algorithme procedure concatener parametres locaux t_liste L1, L2 parametres globaux t_liste Lres variables entier i debut si L1.longueur + L2.longueur <= LMax alors pour i ← 1 jusqu’a L1.longueur faire Lres.elts[i] ← L1.elts[i] fin pour pour i ← L1.longueur+1 jusqu’a L1.longueur + L2.longueur faire Lres.elts[i] ← L2.elts[i-L1.longueur] fin pour Lres.longueur ← L1.longueur + L2.longueur fin si fin algorithme procedure concatener Un peu de complexité : Dans tous les cas, le nombre d’affectations est la somme des longueurs des deux listes. L’opération est-présent opérations est-présent : Liste × Élément → Booléen axiomes est-présent(liste-vide,e) = faux 1 ≤ i ≤ longueur(λ) & e = e′ ⇒ est-présent(insérer(λ, i, e), e′ ) = vrai 1 ≤ i ≤ longueur(λ) & e ̸= e′ ⇒ est-présent(insérer(λ, i, e), e′ ) = est-présent(λ,e′ ) avec λ : Liste e, e′ : Élément i : Entier algorithme fonction est_present : booleen parametres locaux t_element x t_liste L variables entier i debut i ← 1 tant que (i <= L.longueur) et (x <> L.elts[i]) faire i ← i+1 fin tant que retourne (i <= L.longueur) fin algorithme fonction est-present Un peu de complexité : Au pire des cas, cette recherche (dite séquentielle) demande n (la longueur de la liste) comparaisons. Une étude plus approfondie des algorithmes de recherche sera vue en cours. 4