Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Pointeurs, allocation dynamique et listes chaînées
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Les types vus jusqu'à présent (entier, flottant,…) permettaient d'utiliser des variables qui contenaient directement des valeurs. a:entier 5 5 a:entier p: pointeur sur entier Une variable du type pointeur sur T contient, non pas une valeur, mais une adresse, adresse à laquelle on trouve une variable du type T.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Soit T un type quelconque (entier, flottant,…). On note T* le type "pointeur sur T ". On pourra alors déclarer: p : T* 1 – Les pointeurs p est un pointeur sur T p va pouvoir contenir l'adresse mémoire d'une variable de type T
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées *p signifie "valeur se trouvant à l'adresse p ". Soit a de type T: a:T &a signifie "l'adresse de a". 1 – Les pointeurs Les pointeurs sont en fait des adresses mémoire.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Exemple aux p1, p2 : entier*; aux a : entier; a = 2; p1 = &a; p2 = p1; *p1 = 5; écrire(*p2); écrire(*p2 == *p1); écrire(p2 == p1);
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Que fait l'exemple suivant? aux p : entier*; *p = 2; 2 – L'allocation dynamique
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Que fait l'exemple suivant? aux p : entier*; *p = 2; Comme les variables de type classique, les pointeurs ne sont pas initialisés automatiquement! p contient donc une adresse quelconque, c'est un pointeur qui pointe n'importe où. Solution: il faut allouer dynamiquement des ressources, c'est-à-dire demander à réserver une zone mémoire durant l'exécution du programme, ce que nous ne pouvions faire auparavant. On utilisera pour cela le mot-clé nouveau(). nouveau(p) réserve la mémoire nécessaire au type pointé par p et fait pointer p vers cette zone mémoire.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Que fait l'exemple suivant? aux p : entier*; nouveau(p); *p = 2; 2 – L'allocation dynamique
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 1 – Introduction Une liste est une suite finie ordonnée d'éléments de même type. Les éléments sont repérés par leur rang dans la liste. Nous avons déjà utilisé des listes, sous forme de tableau: début Nous allons maintenant définir une nouvelle représentation pour les listes: les listes chaînées.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 2 – Exemple de liste chaînée Une liste chaînée est un ensemble d'éléments où chaque élément (sauf le dernier) est chaîné avec son successeur. Pour accéder à une liste, il suffit de connaître l'adresse de son premier élément. Pour rechercher un élément, on suit le chaînage jusqu'à ce qu'on atteigne l'élément voulu, ou la fin de la liste. début fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 3 – Construction d'une liste chaînée Considérons un article Fiche contenant un nom et un pointeur: Fiche : type article nom : texte; suiv : Fiche*; fin Fiche
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées Écrivons maintenant la fonction construction() qui crée une liste chaînée d'une ou plusieurs Fiches, dans l'ordre inverse de leur saisie: fonction construction() retourne Fiche* {S:renvoie la tête de la liste construite} aux début,cellule:Fiche*, nom:texte; début début=NIL; écrire("Tapez un nom ou STOP pour arrêter"); lire(nom); tant que nom!="STOP" faire nouveau(cellule); (*cellule).nom =nom; (*cellule).suiv=début; début=cellule; fait; retourne(début); fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 3bis – Construction d'une liste chaînée Écrivons maintenant la fonction construction() qui crée une liste chaînée d'une ou plusieurs Fiches, dans l'ordre de leur saisie. Principe: on doit ajouter chaque nouvelle fiche en fin de liste pour cela, on maintient un pointeur sur le dernier élément de la liste
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 4 – Affichage de la liste On souhaite afficher la liste dans son ordre normal. Principe: on parcourt simplement la liste en affichant chaque cellule. Écrivons la procédure affiche(début: Fiche*) :
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 4bis – Affichage de la liste version récursive On souhaite afficher la liste dans son ordre normal. Principe: si la cellule courante est NIL, on quitte la fonction sinon on affiche le contenu de la cellule courante, et on appelle récursivement l'affichage de la cellule suivante Écrivons la procédure affiche(début: Fiche*) :
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 5 – Calcul de la longueur d'une liste Une liste de deux éléments a une longueur 2. Écrivons la fonction longueur(début: Fiche*)retourne entier : fonction longueur(début: Fiche*)retourne entier aux lon: entier, courant: Fiche*; début lon = 0; courant = début; tant que courant != NIL faire lon = lon+1; courant = (*courant).suiv; fait retourne lon; fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 5bis – Calcul de la longueur d'une liste version récursive Une liste de deux éléments a une longueur 2. Écrivons la fonction longueur(début: Fiche*)retourne entier :
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 6 – Recherche d'un élément Écrivons la fonction cherche(début: Fiche*, nom:texte) retourne booléen : fonction cherche(début: Fiche*, nom:texte) retourne booléen {renvoie VRAI si nom est dans la liste, FAUX sinon} aux courant: Fiche*; début courant = début; tant que courant!=NIL ET (*courant).nom!=nom faire courant = (*courant).suiv; fait si courant==NIL alors retourne FAUX; sinon retourne VRAI; fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 6bis – Recherche d'un élément version récursive Une liste de deux éléments a une longueur 2. Principe: si la cellule courante est NIL, on renvoie FAUX si la cellule courante est la cellule recherchée, on renvoie VRAI sinon, on renvoie le résultat de l'appel récursif sur la cellule suivante Écrivons la fonction cherche(début: Fiche*, nom:texte) retourne entier :
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7 – Affichage de la liste inversée On souhaite afficher la liste dans l'ordre inverse. Écrivons la procédure afficheInverse(début: Fiche*) : Pour afficher en ordre inverse, il nous faut mémoriser les éléments au fur et à mesure qu'on parcourt la liste. SOLUTIONS: Utiliser un tableau (quelle taille?) Construire une autre liste chaînée en ordre inverse! CONCLUSION: c'est compliqué!
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive On souhaite afficher la liste dans l'ordre inverse. Principe: si la cellule courante est NIL, on quitte la fonction on appelle récursivement l'affichage de la cellule suivante, PUIS, AU RETOUR DE CET APPEL RECURSIF, on affiche le contenu de la cellule courante. Écrivons la procédure afficheInverse(début: Fiche*) :
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 7bis – Affichage de la liste inversée, version récursive début A B C NIL procédure afficheInv(début: Fiche*) début si début!=NIL alors afficheInv((*début).suiv); écrire((*début).nom); fsi fin
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées 8 – Insertion à la kième position d'une liste On souhaite insérer une nouvelle cellule à la kième position d'une liste. Principe: si on veut insérer à la première position, la tête de la liste change sinon, on doit se positionner sur la k-1ième cellule SI ELLE EXISTE et réaliser l'insertion en modifiant les chaînages correctement. Écrivons la procédure insère(R début: Fiche*, V k:entier, V nom:texte, R erreur:booléen) :