0% ont trouvé ce document utile (0 vote)
51 vues91 pages

DataStructers ABN

Le document présente les structures de données dynamiques, en mettant l'accent sur les listes chaînées et leurs opérations de base. Il décrit les avantages et inconvénients des tableaux par rapport aux listes chaînées, ainsi que les différentes manières d'ajouter, supprimer et parcourir des éléments dans une liste chaînée. Enfin, il fournit des algorithmes et des exemples de code en C pour illustrer la création et la manipulation de listes chaînées simples.

Transféré par

sindasahmima
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
51 vues91 pages

DataStructers ABN

Le document présente les structures de données dynamiques, en mettant l'accent sur les listes chaînées et leurs opérations de base. Il décrit les avantages et inconvénients des tableaux par rapport aux listes chaînées, ainsi que les différentes manières d'ajouter, supprimer et parcourir des éléments dans une liste chaînée. Enfin, il fournit des algorithmes et des exemples de code en C pour illustrer la création et la manipulation de listes chaînées simples.

Transféré par

sindasahmima
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

LES STRUCTURES DE

DONNÉES DYNAMIQUES

anis.bennacib@gmail.com A.U 2023-2024


INTRODUCTION
 Structure de données
o Une manière particulière de stocker et d'organiser les données dans un support afin qu'elles
puissent être utilisées efficacement.
o Il s'agit d'un groupe d'éléments de données regroupés sous un même nom.
o Il est également appelé "Type de données abstrait (ADT)"

 Dans quel but?


Pour plus d'efficacité et la facilité de :
o Stockage des données
o Récupération de données
o Manipulation de données

 Problème de conception :
Le défi est de sélectionner la structure de données la plus appropriée pour le problème
LISTE DES STRUCTURES DE DONNÉES(DE BASE)

Les tableaux(Arrays) Listes chaînées (Linked Lists)

Les Files(Queues) Les Arbres(Trees)


Les Piles(Stacks)
CLASSIFICATION DES STRUCTURES DE DONNÉES
 Basé sur l’existence:

 Structures de données physiques


Peut être créé indépendamment :
• Tableau
• Liste chaînée

 Structures de données logiques


Ne peut pas être créé indépendamment
• Pile
• Files
• Les Arbres
• Les graphes
CLASSIFICATION DES STRUCTURES DE DONNÉES
 Basé sur l’allocation de mémoire :

 Structures de données statiques (ou de taille fixe)

Tels que les tableaux

 Structures de données dynamiques (modifier la taille selon les besoins)

Telles que les listes chaînées


CLASSIFICATION DES STRUCTURES DE DONNÉES
 Basé sur la représentation:

 Structures de données linéaires

• Les tableaux
• Les listes chaînées
• Les piles
• Les files

 Structures de données non linéaires

• Les arbres
• Les graphes
LES OPÉRATIONS DE BASE SUR LES STRUCTURES DE DONNÉES

 Parcourir tous les éléments

 Rechercher un élément ou son emplacement

 Insérer un élément(au début, à la fin, avant ou après un élément donné…),

 Supprimer un élément

 Trier les éléments(croissant ou décroissant)

 Fusionner les éléments de deux (ou plus) structures de données


LES TABLEAUX (ADT)
LES TABLEAUX ADT
 Sauvegarde de donnée
Collection séquentielle des éléments de même type et de nombre fixe.
 Opération
 Créer(Allocation dynamique)

 Remplir un tableau

 Afficher les éléments d'un tableau

 Insérer un élément

 Recherche d'un élément

 Supprimer un élément

 Fusionner deux tableaux(ou plus)


LES LISTES CHAÎNÉES
SIMPLES - DOUBLES - CIRCULAIRES
LISTES CHAÎNÉES (POURQUOI?)
Les tableaux peuvent être utilisés pour stocker des données linéaires de types similaires, mais les
tableaux présentent les limitations suivantes.
 La taille des tableaux est fixe.
 L’insertion d’un nouvel élément dans un tableau d’éléments est coûteuse.
 La suppression est également coûteuse avec les tableaux jusqu’à ce que des techniques spéciales
ne soient utilisées.

 Avantages
 Taille dynamique
 Simplicité d’insertion/suppression

 Inconvénients
 L’accès aléatoire n’est pas autorisé. Nous devons accéder aux éléments séquentiellement à partir du
premier nœud.
 Un espace mémoire supplémentaire pour un pointeur est requis pour chaque élément de la liste.
LES LISTES CHAÎNÉES SIMPLES
I. LISTES CHAÎNÉES SIMPLES
 Définition

Une liste chaînée est une structure dynamique formée d’éléments(nœuds) de même
types reliés par des liens(des pointeurs). Les nœuds de la liste sont éparpillés dans
la mémoire.

Tête

Chaque nœud de la liste est constitué de deux parties :


NULL

un champ qui contient L'adresse


un champ de données de l'élément suivant(Pointeur)
I. LISTES CHAÎNÉES SIMPLES
 Remarques

Tête

NULL

 Une liste chainée est caractérisée par l’adresse de son premier élément(Le pointeur Tête).

 Le dernier élément d’une liste chainée simple contient un pointeur vers NULL.

 Une liste chaînée d'un élément contient un pointeur(tête) vers l'unique nœud de liste qui
pointe vers NULL.
 Le dernier élément existant, son champ suivant vaut NULL.

 Une liste vide ne contient pas de nœud, le pointeur Tête pointe donc vers la valeur NULL.
DÉCLARATION
I. LISTES CHAÎNÉES SIMPLES
 Déclaration En algorithme

TYPE
Nom_noeud= Enregistrement
donnee : Type_donnee
suivant : Pointeur sur Nom_noeud
FinNom_noeud
Nom_Liste = Pointeur sur Nom_noeud

NB.
• La partie "donnée" de nœud peut être de type prédéfini ou définie par l'utilisateur.

• Le pointeur suivant pointe sur l'enregistrement dont il fait partie de ses champs, il s'agit d'une déclaration
récursive.
I. LISTES CHAÎNÉES SIMPLES
 Déclaration En C
//Définition de la structure Nom_Noeud
typedef struct nom_Noeud
{
type_donnee data;
struct nom_noeud* next;
} Nom_Noeud;

//Définition de la liste chaînée


typedef Nom_Noeud * Nom_Liste;

NB.
Pour faciliter la manipulation de la liste, on définit le nouveau type Nom_Liste comme étant un
pointeur sur un Nom_Noeud.
 Créer une Liste chaînée simple(LSC) vide.
 Tester si une LCS est vide
 Ajouter un élément à une LSC(au début, à la fin et
avant ou après un élément donné)
 Parcourir une LCS / Affichage
 Compter le nombre d'éléments d'une LCS
 Supprimer un élément d'une LSC
OPERATIONS SUR LES
 Mettre à jour les données d'un élément d'une LSC
LISTES CHAÎNÉES
 Chercher un élément dans une LSC
SIMPLES
 Trier les éléments d'une LSC(croissant et
décroissant)
 Fusionner deux LSC,
 Etc,
I. LISTES CHAÎNÉES SIMPLES
Soit les déclarations suivantes :

Déclaration En algorithme Déclaration En C

//Définition de la structure Nom_Noeud


TYPE
typedef struct noeud
Noeud = Enregistrement {
donnee : entier int data;
suivant : Pointeur sur Noeud struct noeud* next;
} Noeud;
FinNoeud
//Définition de la liste chaînée
PNoeud = Pointeur sur Noeud typedef Noeud* PNoeud;

NB.
Dans tout ce qui suit, nous supposons qu'une liste chaînée simple contenant les identifiants des membres d'un
club a été créé et qu'on dispose de la variable pointeur "Tete_Liste" qui pointe sur le premier élément de la
liste.
CRÉATION D'UNE LISTE CHAÎNÉE SIMPLE VIDE
(INITIALISATION DE LA LISTE)

TESTER SI UNE LISTE CHAÎNÉE SIMPLE EST


VIDE
I. LISTES CHAÎNÉES SIMPLES
 Création d'une liste chaînée simple vide (initialisation de la liste)

Algorithme de la procédure Creer_Liste


Procédure Créer_Liste(var Tete_Liste : PNoeud)
Début
Tete_Liste ⃪ NULL
Fin

Implémentation de la procédure Creer_Liste en C


PNoeud Creer_Liste(void)
{
int main()
return NULL;
{
}
PNoeud Tete_Liste = Creer_liste();
}
I. LISTES CHAÎNÉES SIMPLES
 Tester si une liste chaînée simple est vide

Algorithme de la fonction estVide


Fonction estVide(Tete_Liste : PNoeud):booléen
Début
Retourner Tete_Liste=NULL
Fin

Implémentation de la procédure Creer_Liste en C


int estVide(PNoeud Tete_Liste)
{
return Tete_Lsite==NULL;
}
AJOUTER UN ÉLÉMENT (NOEUD)
AU DÉBUT(TÊTE) D'UNE LISTE
I. LISTES CHAÎNÉES SIMPLES
 Ajouter un élément(nœud) au début d'une liste(en tête)
 1er cas : La liste est vide  2ème cas : La liste n'est pas vide

221 Tête 201


Tête NULL
NULL

Tête
201
221 201
NULL
NULL

Tête
Tête 201 221 201

NULL NULL
I. LISTES CHAÎNÉES SIMPLES
 Ajouter un élément(nœud) au début d'une liste(en tête)
Algorithme de la procédure Ajouter_Debut

Procédure Ajouter_Début(var Tete_Liste : PNoeud; id : entier)


Var
nouveau : PNoeud
Début
nouveau ⃪ Allouer (taille (Noeud))
*nouveau.donnee ⃪ id
*nouveau.suivant ⃪ Tete_Liste
Tete_Liste ⃪ nouveau
Fin
I. LISTES CHAÎNÉES SIMPLES
 Ajouter un élément(nœud) au début d'une liste(en tête)
Implémentation en C

PNoeud Ajouter_Debut(PNoeud Tete_Liste; int id)


{
PNoeud nouveau = (PNoeud)malloc (sizeof (Noeud));
if(!nouveau)
{
printf("erreur d'allocation ! ");
}
nouveau->donnee = id;
nouveau->suivant = Tete_Liste;
Tete_Liste = nouveau; //Tete_Liste = nouveau;
Return Tete_Liste ;
}
 Remarque :

 Ne pas confondre l’utilisation du point "." et l’utilisation de la flèche "->" pour accéder
aux champs d’une structure. On utilise le point pour une variable de type structure, et
une flèche pour une variable de type pointeur sur structure.

 La fonction renvoie la nouvelle adresse de la tête de liste.

Avec des insertions en tête de liste, la liste obtenue est classée à l’envers, le dernier
élément saisi étant le premier élément de la liste. Pour obtenir les éléments à l’endroit,
il faudrait faire les insertions en queue de liste .
PARCOURIR UNE LISTE CHAÎNÉE
I. LISTES CHAÎNÉES SIMPLES
 Parcourir une liste chaînée simple

L’idée du parcours de liste chaînée est de :


 Prendre un pointeur auxiliaire p.

 On fait pointer p sur la première cellule, puis le pointeur p passe à la cellule suivante (par une

affectation p=p->suivant), etc.

 Le parcours s’arrête lorsque p vaut le suivant de la dernière cellule, c’est-à-dire lorsque p vaut NULL

Tête

NULL
I. LISTES CHAÎNÉES SIMPLES
 Parcourir une liste chaînée simple(dans l'ordre)
Algorithme de la procédure Afficher_LSC

Procédure Afficher_LSC(Tete_Liste : PNoeud)


Var
P : PNoeud
Début
Si estVide(Tete_Liste) Alors
Ecrire("Liste vide")
Sinon
P ⃪ Tete_Liste Répéter
TantQue(P≠NULL)faire Ecrire(*P.donnee)
Ecrire(*P.donnee) Ou bien P ⃪ *P.suivant
P ⃪ *P.suivant Jusqu'à (P = NULL)
finTantQue
finSi
Fin
AJOUTER UN ÉLÉMENT (NOEUD)
EN FIN(QUEUE) D'UNE LISTE
I. LISTES CHAÎNÉES SIMPLES
 Ajouter un élément(nœud) en fin de liste (en queue)
L’insertion d’un élément en queue de liste est un peu plus compliquée que l’insertion en tête de
liste.

 Elle nécessite un parcours de la liste pour rechercher l’adresse du dernier élément.

 La condition d’arrêt est lorsque p->suivant égale à NULL parce que nous cherchons l’adresse
de dernier élément.

 C’est un cas différent du parcours de liste chaînée, où il faut traiter le dernier élément comme
les autres.(Affichage)

 L’insertion en queue de liste permet de saisir une liste chaînée à l’endroit.


I. LISTES CHAÎNÉES SIMPLES
 Ajouter un élément(nœud) en fin de liste (en queue)

Tête

NULL

301
I. LISTES CHAÎNÉES SIMPLES
 Ajouter un élément(nœud) en fin de liste (en queue)

Tête

NULL

301
 Ajouter un élément(nœud) en fin de liste (en queue)
Algorithme de la procédure Ajouter_Fin

Procédure Ajouter_Fin(var Tete_Liste : PNoeud; tel : entier)


Var
P, nouveau : PNoeud
Début
nouveau ⃪ Allouer (taille (Noeud))
*nouveau.donnee ⃪ tel
*nouveau.suivant ⃪ NULL
Si estVide(Tete_Liste) Alors
Tete_Liste ⃪ nouveau
Sinon
P ⃪ Tete_Liste
TantQue(*P.suivant≠NULL)faire
P ⃪ *P.suivant
finTantQue
*P.suivant ⃪ nouveau
finSi
Fin
 Compléments :

 La création d’une liste chaînée par insertions en queue prend un nombre d’opérations
quadratique (O(n2)) par rapport au nombre de nœuds. On peut éviter cela et écrire un
algorithme linéaire (O(n)) en maintenant tout au long de l’algorithme un pointeur sur le
dernier nœud, sans le rechercher à chaque fois par un parcours de liste.

(voir exemple_complet_lsc02.C)
INSÉRER UN ÉLÉMENT (NOEUD) À
UNE POSITION SELON UN CRITÈRE
EXERCICE D’APPLICATION
Écrire un module qui prend en paramètre une liste chaînée supposée triée
dans l'ordre croissant, un entier (val) à insérer dans la liste de façon que les
valeurs entières de liste restent classées en ordre croissant.
I. LISTES CHAÎNÉES SIMPLES
 Insérer un élément dans une liste triée
1er cas : Si la liste est vide, le nouveau élément à insérer devient le premier

Tête
10
nouveau NULL

 2ème cas : La liste n'est pas vide mais il faut insérer au début parce que la nouvelle valeur est inférieure à
celle du premier élément : si nouveau->val < premier->val

Tête
Tête
10 20
10 20
nouveau NULL nouveau
NULL
I. LISTES CHAÎNÉES SIMPLES
 Insérer un élément(Noeud) dans une liste triée
3ème cas : Dernier cas, l'élément est à insérer quelque part dans la liste.
Pour ce faire il faut chercher la bonne place et conserver l'adresse de l'élément qui précède.

Tête
10 30 60 70 140 200

50 NULL

nouveau
I. LISTES CHAÎNÉES SIMPLES
 Insérer un élément(Noeud) dans une liste triée
3ème cas : Dernier cas, l'élément est à insérer quelque part dans la liste.
Pour ce faire il faut chercher la bonne place et conserver l'adresse de l'élément qui précède.

Tête
10 30 60 70 140 200

50 NULL

nouveau
 Insérer un élément(Noeud) dans une liste triée
Algorithme de la procédure Insérer_Asc
Procédure Insérer_Asc(var Tete_Liste : PNoeud; val : entier)
Var
nouveau, courant, precedent : PNoeud
Début
nouveau ⃪ Allouer (taille (Noeud))
*nouveau.donnee ⃪ val
Si (estVide(Tete_Liste) ou *nouveau.donnee≤*Tete_Liste.donnee) Alors
*nouveau.suivant ⃪ Tete_Liste
Tete_Liste ⃪ nouveau
Sinon
courant ⃪ Tete_Liste
precedent ⃪ Tete_Liste
TantQue(courant≠NULL et *nouveau.donnee>*courant.donnee)faire
precedent ⃪ courant
courant ⃪ *courant.suivant
finTantQue
*nouveau.suivant ⃪ courant
*precedent.suivant ⃪ nouveau

finSi
Fin
DÉTRUIRE UNE LISTE CHAÎNÉE
(LIBÉRATION MÉMOIRE)
I. LISTES CHAÎNÉES SIMPLES
Détruire une liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Détruire un liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Détruire un liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Détruire un liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Détruire un liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Détruire un liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
 Détruire un liste chaînée simple.
Pour libérer la mémoire d’une liste chaînée, il faut détruire chacun des éléments(Nœud)

Tête

NULL
I. LISTES CHAÎNÉES SIMPLES
 Détruire un liste chaînée simple.

Algorithme de la procédure Detruire_LSC


Procédure Detruire_LSC (Tete_Liste : PNoeud)
Var
temp : PNoeud
Début
temp ⃪ Tete_Liste
Si estVide(Tete_Liste) Alors
Ecrire("Liste vide")
Sinon
TantQue(Tete_Liste ≠NULL)faire
temp ⃪ Tete_Liste
Tete_Liste ⃪ *Tete_Liste.suivant
Libérer(temp)
finTantQue
finSi
Fin
SUPPRESSION D'UN ÉLÉMENT EN
TÊTE DE LISTE
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en tête de la liste
La suppression du premier élément suppose de bien actualiser la valeur du pointeur premier qui
indique toujours le début de la liste

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en tête de la liste
La suppression du premier élément suppose de bien actualiser la valeur du pointeur premier qui
indique toujours le début de la liste

Tête

10 20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en tête de la liste
La suppression du premier élément suppose de bien actualiser la valeur du pointeur premier qui
indique toujours le début de la liste

Tête

20 70

NULL

Temp
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément en tête de la liste

Algorithme de la procédure Supprimer_Premier


Procédure Supprimer_Premier(Tete_Liste : PNoeud)
Var
temp : PNoeud
Début
temp ⃪ Tete_Liste
Si estVide(Tete_Liste) Alors
Ecrire("Liste vide")
Sinon
temp ⃪ Tete_Liste
Tete_Liste ⃪ *Tete_Liste.suivant
Libérer(temp)
finSi
Fin
SUPPRESSION D'UN ÉLÉMENT EN
FIN DE LISTE
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en fin de la liste
La suppression à la fin suppose de se positionner sur l'avant dernier élément puis de supprimer
le suivant et de mettre suivant à NULL. Il faut que la liste ne soit pas vide et traiter le cas ou il n'y a
qu'un seul élément dans la liste, le premier
1er cas : Si la liste composée d'un seul élément

Tête
10

NULL
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en fin de la liste
La suppression à la fin suppose de se positionner sur l'avant dernier élément puis de supprimer
le suivant et de mettre suivant à NULL. Il faut que la liste ne soit pas vide et traiter le cas ou il n'y a
qu'un seul élément dans la liste, le premier
1er cas : Si la liste composée d'un seul élément

Tête

NULL
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en fin de la liste
La suppression à la fin suppose de se positionner sur l'avant dernier élément puis de supprimer
le suivant et de mettre suivant à NULL. Il faut que la liste ne soit pas vide et traiter le cas ou il n'y a
qu'un seul élément dans la liste, le premier

*(*P.suivant).suivant ≠ NULL

Tête
10 20 70

NULL

P
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en fin de la liste
La suppression à la fin suppose de se positionner sur l'avant dernier élément puis de supprimer
le suivant et de mettre suivant à NULL. Il faut que la liste ne soit pas vide et traiter le cas ou il n'y a
qu'un seul élément dans la liste, le premier

*(*P.suivant).suivant = NULL

Tête
10 20 70

NULL

P
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en fin de la liste
La suppression à la fin suppose de se positionner sur l'avant dernier élément puis de supprimer
le suivant et de mettre suivant à NULL. Il faut que la liste ne soit pas vide et traiter le cas ou il n'y a
qu'un seul élément dans la liste, le premier

Libérer(*P.suivant)

Tête
10 20 70

NULL

P
I. LISTES CHAÎNÉES SIMPLES
Suppression d'un élément en fin de la liste
La suppression à la fin suppose de se positionner sur l'avant dernier élément puis de supprimer
le suivant et de mettre suivant à NULL. Il faut que la liste ne soit pas vide et traiter le cas ou il n'y a
qu'un seul élément dans la liste, le premier

Libérer(*P.suivant)
*P.suivant ⃪NULL
Tête
10 20

NULL

P
SUPPRESSION UN ÉLÉMENT
CORRESPONDANT À UN CRITÈRE
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément correspondant à un critère
 L'objectif cette fois est de supprimer un élément quelconque de la liste en fonction d'un critère
donné.
 Le critère ici est que le champ val de l'élément soit égal à une valeur donnée.

 La recherche s'arrête si un élément répond au critère et nous supprimons uniquement le


premier élément trouvé s'il y en a un.
 Comme pour les suppressions précédentes la liste ne doit pas être vide.

 Il faut prendre en compte le cas où l'élément à supprimer est le premier de la liste.

 Pour tous les autre éléments il faut disposer de l'élément qui précédé celui à supprimer afin de
pouvoir reconstruire la chaine.
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément correspondant à un critère
1er Cas : si la valeur à supprimer est celle du premier élément

Tête
10 20 70

Val = 10
NULL

Precedent
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément correspondant à un critère
1er Cas : si la valeur à supprimer est celle du premier élément

Tête

10 20 70

Val = 10
NULL

aSupprimer
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément correspondant à un critère
1er Cas : si la valeur à supprimer est celle du premier élément

Tête

20 70

Val = 10
NULL
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément correspondant à un critère
2ème Cas : chercher la première occurrence à supprimer

aSupprimer

Tête
10 20 70
Val = 20

NULL

Precedent
I. LISTES CHAÎNÉES SIMPLES
 Suppression d'un élément correspondant à un critère
2ème Cas : chercher la première occurrence à supprimer

aSupprimer

Tête
10 20 70
Val = 20

NULL

Precedent
 Suppression d'un élément correspondant à un critère
Algorithme de la procédure Supprimer_occ1
Procédure Supprimer_Occ1(var Tete_Liste : PNoeud; val : entier)
Var
courant, precedent : PNoeud
Début
Si (estVide(Tete_Liste) Alors
Ecrire("Liste vide !!!!")
Sinon Si(*Tete_Liste.donnee = val) Alors
Supprimer_début(Tete_Liste)
Sinon
courant ⃪ Tete_Liste
TantQue(courant≠NULL && *courant.donnee ≠ val)faire
precedent ⃪ courant
courant ⃪ *courant.suivant
finTantQue
Si courant.donnee = val Alors
*precedent.suivant ⃪ *courant.suivant
Libérer(courant)
finSi

finSi
Fin
LES LISTES DOUBLEMENT CHAÎNÉES

NULL NULL
II. LISTES DOUBLEMENT CHAÎNÉES
 Définition

Une liste doublement chaînée ou bidirectionnelle est telle que chaque élément de la
liste contient un champ qui pointe sur l'élément précédent et un champ qui pointe
sur l'élément suivant.

De ce fait, la liste peut être parcourue dans les deux sens.

Chaque nœud de la liste est constitué de trois parties :

un champ qui contient L'adresse un champ qui contient L'adresse


de l'élément précédent(Pointeur) de l'élément suivant(Pointeur)
un champ de données
DÉCLARATION
II. LISTES DOUBLEMENT CHAÎNÉES
 Déclaration En algorithme

TYPE
Nom_noeud= Enregistrement
donnee : Type_donnee
suivant : Pointeur sur Nom_noeud
precedent : Pointeur sur Nom_noeud
FinNom_noeud
Nom_Liste = Pointeur sur Nom_noeud

NB.
Une liste doublement chaînée peut être représentée par un enregistrement composé de champs :
o Un pointeur sur le premier élément (Tete)
ListeRepere= Enregistrement
o Un pointeur sur le dernier élément (Queue) Tete : Pointeur sur Nom_noeud
Queue : Pointeur sur Nom_noeud
FinListeRepere
II. LISTES DOUBLEMENT CHAÎNÉES
 Déclaration En C
//Définition de la structure Nom_Noeud
typedef struct nom_Noeud
{
type_donnee data;
struct nom_noeud* next;
struct nom_noeud* previous;

} Nom_Noeud;

//Définition de la liste chaînée


typedef Nom_Noeud * Nom_Liste;
NB.
Pour faciliter la manipulation de la liste, on définit le nouveau type Nom_Liste comme étant un
pointeur sur un Nom_Noeud.
II. LISTES DOUBLEMENT CHAÎNÉES
Déclaration d'une structure repère (contient l'adresse du premier et dernier élément)
Pour avoir le contrôle de la liste il est préférable de sauvegarder l'adresse du premier et du
dernier élément.

typedef struct listeRepere


{
struct nom_noeud* tete;
struct nom_noeud* queue;

} Nom_ListeDC;
 Créer une Liste chaînée simple(LDC) vide.
 Tester si une LCS est vide
 Ajouter un élément à une LDC(au début, à la fin
et avant ou après un élément donné)
 Supprimer un élément d'une LDC OPERATIONS SUR LES
 Chercher un élément dans une LDC LISTES DOUBLEMENT
 Trier les éléments d'une LDC(croissant et
décroissant)
CHAÎNÉES
 Fusionner deux LDC,
 Etc..
II. LISTES DOUBLEMENT CHAÎNÉES
Soit les déclarations suivantes :
Déclaration En algorithme Déclaration En C

TYPE //Définition de la structure Nom_Noeud


typedef struct noeud
Noeud = Enregistrement {
donnee : entier int donnee;
suivant : Pointeur sur Noeud struct noeud* suivant;
struct noeud* precedent;
precedent : Pointeur sur Noeud
}Noeud;
FinNoeud // Définition de la structure repère
ListeDC= Enregistrement typedef struct listeRepere
Tete : Pointeur sur Nom_noeud {
struct noeud* tete;
Queue : Pointeur sur Nom_noeud struct noeud* queue;
FinListeDC }ListeDC;
//Définition de la liste chaînée
PNoeud = Pointeur sur Nœud typedef Noeud* PNoeud;
PListeDC = Pointeur sur ListeDC typedef ListeDC* PListeDC;
CRÉATION D'UNE LISTE DOUBLEMENT CHAÎNÉE
VIDE (INITIALISATION DE LA LISTE)

TESTER SI UNE LISTE DOUBLEMENT CHAÎNÉE


EST VIDE
II. LISTES DOUBLEMENT CHAÎNÉES
 Création d'une liste chaînée simple vide (initialisation de la liste)

Algorithme de la procédure Creer_Liste


Procédure Créer_Liste(var LDC : PListeDC)
Début
LDC->Tete ⃪ NULL
LDC->Queue ⃪ NULL
Fin

Implémentation de la procédure Creer_Liste en C


void initialisation(PListeDC LDC)
{
int main()
LDC->tete = NULL;
{
LDC->queue =NULL;
PListeDC LDC = (PListeDC)malloc(sizeof(ListeDC));
}
initialisation(LDC);
}
II. LISTES DOUBLEMENT CHAÎNÉES
 Tester si une liste doublement chaînée est vide

Algorithme de la fonction estVide


Fonction estVide(LDC : PListeDC):booléen
Début
Retourner LDC->Tete=NULL
Fin

Implémentation de la procédure Creer_Liste en C


int estVide(PListeDC LDC)
{
return LDC->Tete==NULL;
}
AJOUTER UN ÉLÉMENT (NOEUD)
AU DÉBUT(TÊTE) D'UNE LISTE
DOUBLEMENT CHAÎNÉE
II. LISTES DOUBLEMENT CHAÎNÉES
 Ajouter un élément(nœud) au début d'une liste(en tête)
 1er cas : La liste est vide

Tete Queue

NULL

Tete Queue Tete Queue

1 1 1
NULL NULL NULL NULL NULL
II. LISTES DOUBLEMENT CHAÎNÉES
 Ajouter un élément(nœud) au début d'une liste(en tête)
 2ème cas : La liste n'est pas vide
Tete Queue

1 2
NULL NULL

Tete Queue

0 1 2
NULL NULL

NULL
II. LISTES DOUBLEMENT CHAÎNÉES
 Ajouter un élément(nœud) au début d'une liste(en tête)
 2ème cas : La liste n'est pas vide
Tete Queue

1 2
NULL NULL

Tete Queue

0 1 2
NULL NULL
II. LISTES DOUBLEMENT CHAÎNÉES
 Ajouter un élément(nœud) au début d'une liste(en tête)
 2ème cas : La liste n'est pas vide
Tete Queue

1 2
NULL NULL

Tete Queue

0 1 2
NULL NULL
II. LISTES DOUBLEMENT CHAÎNÉES
 Ajouter un élément(nœud) au début d'une liste(en tête)

Procédure Ajout_Tete (var LDC : PListeDC; val : Entier)


Var
nouveau : PNoeud
Début
nouveau ⃪ allouer (taille (Noeud))
*nouveau.donnee ⃪ val
*nouveau.precedent ⃪ NULL
*nouveau.suivant ⃪ TeteListe
Si (LDC->Tete ≠ NULL) alors
LDC->Tete.precedent ⃪ nouveau
FinSi
LDC->Tete ⃪ nouveau
Si (LDC->Queue = NULL) alors
LDC->Queue ⃪ nouveau
FinSi
Fin
II. LISTES DOUBLEMENT CHAÎNÉES
 Ajouter un élément(nœud) au début d'une liste(en tête) En C
void InsererEnTete(PListeDC LDC, int NvDonnee)
{
PNoeud nouveau = (PNoeud)malloc(sizeof(Noeud));
if(!nouveau) { puts("Mémoire insuffisainte !"); exit(EXIT_FAILURE); }
nouveau->donnee = NvDonnee; //ou bien (*nouveau).donnee = NvDonnee
nouveau->precedent = NULL;
if(estVide(LDC))
{
nouveau->suivant = NULL;
LDC->queue = nouveau;
}
else
{
nouveau->suivant = LDC->tete;
LDC->tete->precedent = nouveau;
}
LDC->tete = nouveau;
}

Vous aimerez peut-être aussi