#include <stdio.h> #include <stdlib.h> struct cell int clef; struct cell suiv; ; / longueur. pc->suiv est l abréviation de (pc).suiv. pour cette fonction comme pour les suivantes, on donne, lorsqu il existe une version non-récursive et une récursive, les deux versions. / int longueur(struct cell pc) int nbr = 0; nbr++; return nbr; int longueur_rec(struct cell pc) if (pc == NULL) return 0; return 1 + longueur_rec(pc->suiv); / afficher La version récursive n est demandée que pour la forme : elle est n est pas plus simple que la version non récursive si l on souhaite éviter l affichage de "Liste Vide" après le dernier élément de la liste ou l affichage de \n multiples. / void afficher (struct cell pc) if (pc == NULL) printf("liste Vide"); else printf("%d ",pc->clef); printf("\n"); void afficher_rec(struct cell pc) if (pc == NULL) printf("liste Vide\n"); else 1
2 printf("%d ",pc->clef); if (pc->suiv!= NULL) afficher_rec(pc->suiv); else printf("\n"); / empiler rien de difficile. / struct cell empiler(struct cell pc, int n) struct cell pn = malloc(sizeof(struct cell)); / ajouter. la version non récursive est plus complexe : on crée la cellule pn à ajouter. si la liste est vide : on renvoie la liste réduite à pn. sinon : à l aide du pointeur mobile pm, on parcourt la liste, jusqu à la dernière cellule. on chaîne cette cellule avec la cellule crée. on renvoie l adresse de la première cellule. pour la version récursive : si la liste est vide : on crée la cellule pn à ajouter. on renvoie la liste réduite à pn. sinon : on chaîne la première cellule à la liste obtenue par ajout d une nouvelle cellule à pc->suiv. on renvoie l adresse de la première cellule. / struct cell ajouter(struct cell pc, int n) struct cell pn = malloc(sizeof(struct cell)); if (pc == NULL) pn->suiv = NULL; else struct cell pm = pc; while (pm->suiv!=null) pm = pm->suiv; pm->suiv = pn; pn->suiv = NULL;
3 struct cell ajouter_rec(struct cell pc, int n) if (pc == NULL) struct cell pn = malloc(sizeof(struct cell)); else pc->suiv = ajouter_rec(pc->suiv,n); / depiler rien de difficile. / struct cell depiler(struct cell pc) if (pc!= NULL) struct cell pcs = pc->suiv; pc = pcs; / supprimer il faut, quel que soit la version, distinguer les cas : - liste vide - liste à un seul élément - liste à au moins deux éléments dans la version non-récursive, la difficulté est d avancer dans la liste jusqu à l avant-dernière cellule. / struct cell supprimer(struct cell pc) if (pc->suiv == NULL) return NULL; struct cell pm = pc; while (pm->suiv->suiv!= NULL) pm = pm->suiv; free(pm->suiv); pm->suiv = NULL;
4 struct cell supprimer_rec(struct cell pc) if (pc->suiv == NULL) return NULL; pc->suiv = supprimer_rec(pc->suiv); / detruire / void detruire(struct cell pc) while (pc!= NULL) pc = depiler(pc); void detruire_rec(struct cell pc) if (pc!= NULL) detruire_rec (pc->suiv); / copier la version récursive est de loin la plus simple. pour la non-récursive, on a, à partir de la seconde itération : - ppc pointe vers la toute première cellule créée, - pn recoit l adresse d une nouvelle cellule, - pnp pointe vers la cellule crée à l étape précédente, Noter que l on est obligé de distinguer la première étape des suivantes (à la 1ère, ppc pointe vers NULL, sa valeur d initialisation avant la boucle). / struct cell copier(struct cell pc) struct cell ppc = NULL, pnp; struct cell pn = malloc(sizeof(struct cell)); pn->clef = pc->clef; if (ppc == NULL) ppc = pn; pnp = pn; else pnp = pn; pnp->suiv = pn; pnp->suiv = NULL; return ppc;
5 struct cell copier_rec(struct cell pc) struct cell pcc = copier_rec(pc->suiv); return empiler(pcc,pc->clef); / chainer la version récursive est encore la plus compacte. / struct cell chainer(struct cell pc1, struct cell pc2) if (pc1 == NULL) return pc2; struct cell pm = pc1; while (pm->suiv!= NULL) pm = pm->suiv; pm->suiv = pc2; return pc1; struct cell chainer_rec(struct cell pc1, struct cell pc2) if (pc1 == NULL) return pc2; pc1->suiv = chainer_rec(pc1->suiv,pc2); return pc1; / inserer_trie et copier_trie la version non-récursive est un cauchemar à écrire correctement. en pratique, ce genre de fonction doit être écrit par récurrence. / struct cell inserer_trie(struct cell pc, int n) struct cell pn = malloc(sizeof(struct cell)); if (pc == NULL pc->clef >= n) struct cell pm = pc; while (pm->suiv!= NULL && pm->suiv->clef < n) pm = pm->suiv; pn->suiv = pm->suiv; pm->suiv = pn; struct cell inserer_trie_rec(struct cell pc, int n) if (pc == NULL pc->clef >= n)
6 struct cell pn = malloc(sizeof(struct cell)); pc->suiv = inserer_trie_rec(pc->suiv,n); struct cell copier_trie(struct cell pc) struct cell pct = NULL; pct = inserer_trie(pct,pc->clef); afficher_rec(pct); return pct; / inversion on réorganise en pci la liste pc, par itération. un exemple de fonction sur les listes où une écriture par récurrence serait inefficace. / struct cell inverser(struct cell pc) struct cell pci = NULL; struct cell pctmp = pc->suiv; pc->suiv = pci; pci = pc; pc = pctmp; return pci; main()