Académique Documents
Professionnel Documents
Culture Documents
Cette article a pour but la comprhension des listes simplement chanes. L'implmentation en fonction des besoins et des performances vous appartient. Les listes chanes peuvent tre utilises quand plusieurs oprations d'insertion/suppression d'lments sont ncessaires.
Dfinition
Les listes chanes sont des structures de donnes semblables aux tableaux sauf que l'accs un lment ne se fait pas par index mais l'aide d'un pointeur. L'allocation de la mmoire est faite au moment de l'excution. Dans une liste les lments sont contigus en ce qui concerne l'enchanement.
En revanche, par rapport aux tableaux o les lments sont contigus dans la mmoire, les lments d'une liste sont parpills dans la mmoire. La liaison entre les lments se fait grce un pointeur. En ralit, dans la mmoire la reprsentation est alatoire en fonction de l'espace allou. Le pointeur suivant du dernier lment doit pointer vers NULL (la fin de la liste). Pour accder un lment la liste est parcourue en commenant avec la tte, le pointeur suivant permettant le dplacement vers le prochain lment. Le dplacement se fait dans une seule direction, du premier vers le dernier lment. Si vous voulez vous dplacer dans les deux directions (en avant/en arrire) utilisez les listes doublement chanes.
typedef struct ElementListe { char }Element; Pour avoir le contrle de la liste il est prfrable de sauvegarder certains lments : le premier lment, le dernier lment, le nombre d'lments. *donnee; struct ElementListe *suivant;
Pour raliser cela une autre structure sera utilise (ce n'est pas obligatoire, des variables peuvent tre utilises). Voici sa composition: typedef struct ListeRepere { Element *debut; Element *fin; int taille; }Liste; Le pointeur debut contiendra l'adresse du premier lment de la liste. Le pointeur fin contiendra l'adresse du dernier lment de la liste. La variable taille contient le nombre d'lments. Quelque soit la position dans la liste, les pointeurs debut et fin pointent toujours respectivement vers le 1er et le dernier lment. Le champ taille contiendra le nombre d'lments de la liste quelque soit l'opration effectue sur la liste.
Initialisation
Prototype de la fonction : void initialisation (Liste *liste); Cette opration doit tre faite avant toute autre opration sur la liste. Elle initialise le pointeur debut et le pointeur fin avec le pointeur NULL, et la taille avec la valeur
0. La fonction void initialisation (Liste *liste){ liste->debut = NULL; liste->fin = NULL; taille = 0; }
Pour ajouter un lment dans la liste il y a plusieurs situations : 1. Insertion dans une liste vide 2. Insertion au dbut de la liste 3. Insertion la fin de la liste 4. Insertion ailleurs dans la liste
le pointeur suivant du nouvel lment pointera vers NULL (vu que l'insertion est faite dans une liste vide on utilise l'adresse du pointeur debut qui vaut NULL) les pointeurs debut et fin pointeront vers le nouvel lment la taille est mise jour
La fonction /* insertion dans une liste vide */ int ins_dans_liste_vide (Liste * liste, char *donnee){ Element *nouveau_element; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nouveau_element->donnee, donnee); nouveau_element->suivant = NULL; liste->debut = nouveau_element; liste->fin = nouveau_element; liste->taille++; return 0; }
tapes: allocation de la mmoire pour le nouvel lment remplir le champ de donnes du nouvel lment le pointeur suivant du nouvel lment pointe vers le 1er lment le pointeur debut pointe vers le nouvel lment le pointeur fin ne change pas la taille est incrmente
La fonction /* insertion au dbut de la liste */ int ins_debut_liste (Liste * liste, char *donnee){ Element *nouveau_element; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nouveau_element->donnee, donnee); nouveau_element->suivant = liste->debut; liste->debut = nouveau_element;
liste->taille++; return 0; }
La fonction /*insertion la fin de la liste */ int ins_fin_liste (Liste * liste, Element * courant, char *donnee){ Element *nouveau_element; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL)
return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nouveau_element->donnee, donnee); courant->suivant = nouveau_element; nouveau_element->suivant = NULL; liste->fin = nouveau_element; liste->taille++; return 0; }
La fonction /* insertion la position demande */ int ins_liste (Liste * liste, char *donnee, int pos){ if (liste->taille < 2) return -1; if (pos < 1 || pos >= liste->taille) return -1; Element *courant; Element *nouveau_element; int i; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; courant = liste->debut; for (i = 1; i < pos; ++i) courant = courant->suivant;
if (courant->suivant == NULL) return -1; strcpy (nouveau_element->donnee, donnee); nouveau_element->suivant = courant->suivant; courant->suivant = nouveau_element; liste->taille++; return 0; }
Faire pointer le pointeur suivant de l'lment courant vers l'adresse du pointeur suivant de l'lment supprimer librer la mmoire occupe par l'lment supprim mettre jour la taille de la liste
Pour supprimer un lment dans la liste il y a plusieurs situations : 1. Suppression au dbut de la liste 2. Suppression ailleurs dans la liste
tapes: le pointeur supp_elem contiendra l'adresse du 1er lment le pointeur debut pointera vers le 2me lment la taille de la liste sera dcrmente d'un lment
La fonction /* suppression au dbut de la liste */ int supp_debut (Liste * liste){ if (liste->taille == 0) return -1; Element *supp_element; supp_element = liste->debut; liste->debut = liste->debut->suivant; if (liste->taille == 1) liste->fin = NULL; free (supp_element->donnee); free (supp_element); liste->taille--; return 0; }
tapes: le pointeur supp_elem contiendra l'adresse vers laquelle pointe le pointeur suivant d'lment courant le pointeur suivant de l'lment courant pointera vers l'lment sur lequel pointe le pointeur suivant de l'lment qui suit l'lment courant dans la liste Si l'lment courant est l'avant dernier lment, le pointeur fin doit tre mis jour la taille de la liste sera dcrmente d'un lment
La fonction /* supprimer un element aprs la position demande */ int supp_dans_liste (Liste * liste, int pos){ if (liste->taille <= 1 || pos < 1 || pos >= liste->taille) return -1; int i; Element *courant; Element *supp_element; courant = liste->debut; for (i = 1; i < pos; ++i) courant = courant->suivant; supp_element = courant->suivant; courant->suivant = courant->suivant->suivant; if(courant->suivant == NULL) liste->fin = courant; free (supp_element->donnee); free (supp_element); liste->taille--; return 0; }
Affichage de la liste
Pour afficher la liste entire il faut se positionner au dbut de la liste (le pointeur debut le permettra). Ensuite en utilisant le pointeur suivant de chaque lment la liste est parcourue du 1er vers le dernier lment. La condition d'arrt est donne par le pointeur suivant du dernier lment qui vaut NULL. La fonction /* affichage de la liste */ void affiche (Liste * liste){ Element *courant; courant = liste->debut; while (courant != NULL){ printf ("%p - %s\n", courant, courant->donnee); courant = courant->suivant; } }
Destruction de la liste
Pour dtruire la liste entire, j'ai utilis la suppression au dbut de la liste tant que la taille est plus grande que zro. La fonction /* dtruire la liste */ void detruire (Liste * liste){ while (liste->taille > 0) supp_debut (liste); }
Exemple complet
liste.h
/* ---------- liste.h ----------- */ typedef struct ElementListe { char *donnee; struct ElementListe *suivant; } Element; typedef struct ListeRepere { Element *debut; Element *fin; int taille; } Liste; /* initialisation de la liste */ void initialisation (Liste * liste);
/* INSERTION */ /* insertion dans une liste vide */ int ins_dans_liste_vide (Liste * liste, char *donnee); /* insertion au dbut de la liste */ int ins_debut_liste (Liste * liste, char *donnee); /* insertion a fin de la liste */ int ins_fin_liste (Liste * liste, Element * courant, char *donnee);
/* insertition ailleurs */ int ins_liste (Liste * liste, char *donnee, int pos);
/* SUPPRESSION */ int supp_debut (Liste * liste); int supp_dans_liste (Liste * liste, int pos);
int menu (Liste *liste,int *k); void affiche (Liste * liste); void detruire (Liste * liste); /* -------- FIN liste.h --------- */
liste_function.h
/***************************\
liste_function.h
\***************************/ void initialisation (Liste * liste) { liste->debut = NULL; liste->fin = NULL; liste->taille = 0; } /* insertion dans une liste vide */ int ins_dans_liste_vide (Liste * liste, char *donnee){ Element *nouveau_element; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nouveau_element->donnee, donnee); nouveau_element->suivant = NULL; liste->debut = nouveau_element; liste->fin = nouveau_element;
liste->taille++; return 0; } /* insertion au dbut de la liste */ int ins_debut_liste (Liste * liste, char *donnee){ Element *nouveau_element; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nouveau_element->donnee, donnee); nouveau_element->suivant = liste->debut; liste->debut = nouveau_element; liste->taille++; return 0; } /*insertion la fin de la liste */ int ins_fin_liste (Liste * liste, Element * courant, char *donnee){ Element *nouveau_element; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; strcpy (nouveau_element->donnee, donnee); courant->suivant = nouveau_element; nouveau_element->suivant = NULL; liste->fin = nouveau_element; liste->taille++; return 0; } /* insertion la position demande */ int ins_liste (Liste * liste, char *donnee, int pos){ if (liste->taille < 2) return -1; if (pos < 1 || pos >= liste->taille) return -1;
Element *courant; Element *nouveau_element; int i; if ((nouveau_element = (Element *) malloc (sizeof (Element))) == NULL) return -1; if ((nouveau_element->donnee = (char *) malloc (50 * sizeof (char))) == NULL) return -1; courant = liste->debut; for (i = 1; i < pos; ++i) courant = courant->suivant; if (courant->suivant == NULL) return -1; strcpy (nouveau_element->donnee, donnee); nouveau_element->suivant = courant->suivant; courant->suivant = nouveau_element; liste->taille++; return 0; } /* suppression au dbut de la liste */ int supp_debut (Liste * liste){ if (liste->taille == 0) return -1; Element *supp_element; supp_element = liste->debut; liste->debut = liste->debut->suivant; if (liste->taille == 1) liste->fin = NULL; free (supp_element->donnee); free (supp_element); liste->taille--; return 0; } /* supprimer un element aprs la position demande */ int supp_dans_liste (Liste * liste, int pos){ if (liste->taille <= 1 || pos < 1 || pos >= liste->taille) return -1; int i; Element *courant; Element *supp_element;
courant = liste->debut; for (i = 1; i < pos; ++i) courant = courant->suivant; supp_element = courant->suivant; courant->suivant = courant->suivant->suivant; if(courant->suivant == NULL) liste->fin = courant; free (supp_element->donnee); free (supp_element); liste->taille--; return 0; } /* affichage de la liste */ void affiche (Liste * liste){ Element *courant; courant = liste->debut; while (courant != NULL){ printf ("%p - %s\n", courant, courant->donnee); courant = courant->suivant; } } /* detruire la liste */ void detruire (Liste * liste){ while (liste->taille > 0) supp_debut (liste); } int menu (Liste *liste,int *k){ int choix; printf("********** MENU **********\n"); if (liste->taille == 0){ printf ("1. Ajout du 1er element\n"); printf ("2. Quitter\n"); }else if(liste->taille == 1 || *k == 1){ printf ("1. Ajout au debut de la liste\n"); printf ("2. Ajout a la fin de la liste\n"); printf ("4. Suppression au debut de la liste\n"); printf ("6. Detruire la liste\n"); printf ("7. Quitter\n"); }else { printf ("1. Ajout au debut de la liste\n"); printf ("2. Ajout a la fin de la liste\n");
printf ("3. Ajout apres la position specifie\n"); printf ("4. Suppression au debut de la liste\n"); printf ("5. Suppression apres la position specifie\n"); printf ("6. Detruire la liste\n"); printf ("7. Quitter\n"); } printf ("\n\nFaites votre choix : "); scanf ("%d", &choix); getchar(); if(liste->taille == 0 && choix == 2) choix = 7; return choix; } /* -------- FIN liste_function.h --------- */
liste.c
/**********************\
liste.c
\**********************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "liste.h" #include "liste_function.h" int main (void) { char choix; char *nom; Liste *liste; Element *courant; if ((liste = (Liste *) malloc (sizeof (Liste))) == NULL) return -1; if ((nom = (char *) malloc (50)) == NULL) return -1; courant = NULL; choix = 'o'; initialisation (liste); int pos, k;
while (choix != 7){ choix = menu (liste, &k); switch (choix){ case 1: printf ("Entrez un element : "); scanf ("%s", nom); getchar (); if (liste->taille == 0) ins_dans_liste_vide (liste, nom); else ins_debut_liste (liste, nom); printf ("%d elements:deb=%s,fin=%s\n", liste->taille, liste->debut->donnee, liste->fin->donnee); affiche (liste); break; case 2: printf ("Entrez un element : "); scanf ("%s", nom); getchar (); ins_fin_liste (liste, liste->fin, nom); printf ("%d elements:deb=%s,fin=%s\n", liste->taille, liste->debut->donnee, liste->fin->donnee); affiche (liste); break; case 3: printf ("Entrez un element : "); scanf ("%s", nom); getchar (); do{ printf ("Entrez la position : "); scanf ("%d", &pos); } while (pos < 1 || pos > liste->taille); getchar (); if (liste->taille == 1 || pos == liste->taille){ k = 1; printf("-----------------------------------------------\n"); printf("/!\\Insertion echoue.Utilisez le menu {1|2} /!\\\n"); printf("-----------------------------------------------\n"); break; } ins_liste (liste, nom, pos); printf ("%d elements:deb=%s,fin=%s\n", liste->taille, liste->debut->donnee, liste->fin->donnee);
affiche (liste); break; case 4: supp_debut (liste); if (liste->taille != 0) printf ("%d elements:deb=%s,fin=%s\n", liste->taille, liste->debut->donnee, liste->fin->donnee); else printf ("liste vide\n"); affiche (liste); break; case 5: do{ printf ("Entrez la position : "); scanf ("%d", &pos); } while (pos < 1 || pos > liste->taille); getchar (); supp_dans_liste (liste, pos); if (liste->taille != 0) printf ("%d elements:deb=%s,fin=%s\n", liste->taille, liste->debut->donnee, liste->fin->donnee); else printf ("liste vide\n"); affiche (liste); break; case 6: detruire (liste); printf ("la liste a ete detruite : %d elements\n", liste>taille); break; } } return 0; }