Seance6 ALgo ENSAB Mode
Seance6 ALgo ENSAB Mode
CHAÎNÉES
DÉFINITION
2
1. DÉFINITION
Les Listes Doublement Chaînées sont des structures de
données semblables aux listes simplement chaînées :
3
1. DÉFINITION
Pour accéder à un élément de la liste doublement
chaînée :
1 2 7 5 3
tete queue
4
2. CONSTRUCTION DU PROTOTYPE D'UN ÉLÉMENT
DE LA LISTE
Pour définir un élément de la liste le type struct sera utilisé
5
2. CONSTRUCTION DU PROTOTYPE D'UN ÉLÉMENT
DE LA LISTE
Exemple 1 : représentation d’une liste de 5 éléments ‘A’,
‘B’,‘C’,‘D’ et ‘E’
typedef struct ElementListe {
char donnee ;
struct ElementListe *precedent ;
struct ElementListe *suivant ; } Liste;
Pour avoir le contrôle de la liste il est préférable de
sauvegarder certains éléments : debut, fin, taille
Le pointeur debut contiendra l'adresse du premier élément de
la liste. Liste *debut ;
Le pointeur fin contiendra l'adresse du dernier élément de la
liste. Liste *fin ;
La variable taille contient le nombre d'éléments. int taille ;
A B C D E
debut fin
6
3. OPÉRATIONS SUR LES LISTES DOUBLEMENT
CHAÎNÉES
int Taille ;
Element *Debut, *Fin;
7
3. OPÉRATIONS SUR LES L.D.C.
Initialisation
La fonction
initialisation ( ) {
Debut = NULL;
Fin = NULL;
Taille = 0; }
8
3. OPÉRATIONS SUR LES L.D.C.
Insertion d'un élément dans la liste
9
3. OPÉRATIONS SUR LES L.D.C.
Insertion d'un élément dans la liste
10
3. OPÉRATIONS SUR LES L.D.C.
Insertion d'un élément dans la liste
Étapes :
11
3. OPÉRATIONS SUR LES L.D.C.
Insertion d'un élément dans la liste
12
3. OPÉRATIONS SUR LES L.D.C.
Insertion d'un élément dans la liste
2. Insertion au début de la liste
Étapes
13
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
14
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
Étapes :
• allocation de la mémoire pour le nouvel élément
• remplir le champ de données du nouvel élément
• le pointeur suivant du nouvel élément pointe vers NULL
• le pointeur precedent du nouvel élément pointe vers le dernier
élément (le pointeur Fin)
• le pointeur suivant du dernier élément va pointer vers le nouvel
élément
• le pointeur Fin pointe vers le nouvel élément
• le pointeur Debut ne change pas
• la Taille est incrémentée
15
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
16
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
argument à la fonction.
17
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
4. avant un élément de la liste
Étapes :
• allocation de la mémoire pour le nouvel élément
• remplir le champ de données du nouvel élément
• choisir une position dans la liste
• le pointeur suivant du nouvel élément pointe vers l'élément courant
• le pointeur precedent du nouvel élément pointe vers l'adresse sur la
quelle pointe le pointeur precedent d'élément courant
• si le pointeur precedent de l'élément courant est NULL alors le
pointeur Debut pointe vers le nouvel élément
• sinon le pointeur suivant de l'élément qui précède l'élément courant
pointera vers le nouvel élément
• le pointeur precedent d'élément courant pointe vers le nouvel élément
• le pointeurs Fin ne change pas
• la Taille est incrémentée d'une unité
18
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
4. Insertion avant un élément de la liste
int ins_avant (char *info, int pos) {
int i;
Element *nou_element, *courant;
if ((nou_element = (Element*) malloc (sizeof (Element))) ==NULL)
return -1;
nou_element->info = (char *) malloc (50 * sizeof(char));
strcpy (nou_element->info, info);
courant = Debut;
for (i = 1; i < pos; ++i) courant = courant->suivant;
nou_element->suivant = courant;
nou_element-> precedent = courant->precedent;
if(courant->precedent == NULL) Debut = nou_element;
else courant->precedent->suivant = nou_element;
courant->precedent = nou_element;
Taille++;
return 0; }
19
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
5. Insertion après un élément de la liste
• Étapes:
• allocation de la mémoire pour le nouvel élément
• remplir le champ de données du nouvel élément
• choisir une position dans la liste
• le pointeur suivant du nouvel élément pointe vers l'adresse sur la
quelle pointe le pointeur suivant d'élément courant
• le pointeur precedent du nouvel élément pointe vers l'élément
courant.
• si le pointeur suivant de l'élément courant est NULL alors le
pointeur Fin pointe vers le nouvel élément
• sinon le pointeur precedent de l'élément qui succède l'élément
courant pointera vers le nouvel élément
• le pointeur suivant d'élément courant pointe vers le nouvel élément
• la Taille est incrémentée d'une unité
20
3. OPÉRATIONS SUR LES L.D.C
Insertion d'un élément dans la liste
21
3. OPÉRATIONS SUR LES L.D.C
Suppression d'un élément dans la liste
C'est la raison pour la quelle nous allons créer une seule fonction
22
3. OPÉRATIONS SUR LES L.D.C
Suppression d'un élément dans la liste
Étapes:
23
3. OPÉRATIONS SUR LES L.D.C
Suppression d'un élément dans la liste
Étapes:
24
3. OPÉRATIONS SUR LES L.D.C
Suppression d'un élément dans la liste
25
3. OPÉRATIONS SUR LES L.D.C
Suppression d'un élément dans la liste
26
3. OPÉRATIONS SUR LES L.D.C
Affichage de la liste
27
3. OPÉRATIONS SUR LES L.D.C
Affichage de la liste
28
3. OPÉRATIONS SUR LES L.D.C
Destruction de la liste
La fonction
detruire () {
while (Taille > 0) supp(1);
}
29
4. EXERCICE
• L’objectif de ce problème est d’écrire un programme qui permet de
faire la somme de deux grands nombres entiers. Pour réaliser cet
objectif on doit lire une chaîne de caractères représentant un grand
nombre entier et le charger par paquets de 4 chiffres dans une liste
simplement chaînée.
• Pour définir un élément de la liste le type struct sera utilisé.
L'élément de la liste contiendra un champ info de type entier qui
représente les 4 chiffres du paquet et un pointeur suivant. Le
pointeur suivant est du même type que l'élément, sinon il ne
pourra pas pointer vers l'élément. Le pointeur suivant permettra
l'accès vers le prochain élément.
30
4. EXERCICE
• Chaque nombre est donc représenté par une liste simplement
chaînée et pour avoir le contrôle de la liste, il est préférable de
sauvegarder les éléments suivants :
• Le pointeur debut contiendra l'adresse du premier élément de la
liste.
• Le pointeur fin contiendra l'adresse du dernier élément de la liste.
• La variable Npaquets contient le nombre d'éléments (nombre de
paquets).
•
• Pour simplifier l’écriture du programme et pour ne pas avoir
plusieurs variables globales, une autre structure de donnée doit
être ajouté (obligatoire) pour représenter les nombres à
additionner (Nombre1 et Nombre2) et le nombre somme
(Nombre3) :
31
4. EXERCICE
typedef struct Nombre {
Element *debut;
Element *fin;
int Npaquets; } GrandNombre;
32
4. EXERCICE
• 1- Ecrire la fonction qui permet d’initialiser les pointeurs Debut et Fin
à NULL et le Npaquets avec la valeur 0.
33
4. EXERCICE
• 2- Ecrire la fonction qui permet d’insérer un élément dans une liste
vide
34
4. EXERCICE
• 3- Ecrire la fonction qui permet d’insérer un élément à la fin de la liste
35
4. EXERCICE
• 4- Ecrire la fonction qui permet de charger une chaîne de caractères
par paquets de 4 chiffres dans la liste.
• Prototype de la fonction : convertir(GrandNombre *Nb, char *chaine);
Convertir(GrandNombre *Nb, char *chaine) {
int Long, reste, i, val, N, t;
char ch4[4], ch_reste[4],*ch;
Long= strlen(chaine); N=Long/4;
for (i=0; i<N; i++) {
val=Long - 4*(i+1); ch=&chaine[val]; strncpy(ch4, ch, 4); t=atoi(ch4);
if (Nb->Npaquets==0) ins_dans_liste_vide(Nb,t);
else ins_fin_liste (Nb,t); };
reste=Long%4;
if (reste!=0) {
ch=&chaine[0]; strncpy(ch_reste, ch, reste); t=atoi(ch_reste);
if (Nb->Npaquets==0) ins_dans_liste_vide(Nb,t);
else ins_fin_liste (Nb,t); }
}
36
4. EXERCICE
• 5- Ecrire la fonction qui permet de faire la somme de deux grands
nombres
• Prototype de la fonction : somme(GrandNombre Nb1, GrandNombre Nb2,
• GrandNombre *Nb3);
somme(GrandNombre Nb1, GrandNombre Nb2, GrandNombre *Nb3) {
int s, t, i, ret=0;
Element *element1, *element2 ;
element1=Nb1.Debut; element2=Nb2.Debut;
for (i=1; i<=Nb1.Npaquets;i++) {
s = element1->info + element2->info + ret;
t = s%10000;
if (Nb3->Npaquets==0) ins_dans_liste_vide(Nb3,t);
else ins_fin_liste (Nb3,t);
ret= s/10000;
element1=element1->suivant; element2=element2->suivant;
}; //fin de for
37
4. EXERCICE
• 5- Ecrire la fonction qui permet de faire la somme de deux grands
nombres
• Prototype de la fonction : somme(GrandNombre Nb1, GrandNombre Nb2, GrandNombre *Nb3);
38
4. EXERCICE
6- Ecrire la fonction qui permet d’afficher la liste entière à l’envers
Prototype de la fonction : afficher_envers(GrandNombre Nb);
afficher(GrandNombre Nb) {
char ch[4];
int i,s;
Element *element;
element=Nb.Debut;
sprintf(ch,"%d", element->info); printf("%s \n",ch);
for (i=2;i<=Nb.Npaquets; ++i) {
element=element->suivant; s=element->info;
if (s<=9) sprintf(ch,"000%d", s);
else if (s<=99) sprintf(ch,"00%d", s);
else if (s<=999) sprintf(ch,"0%d", s);
else sprintf(ch,"%d", s);
printf("%s \n",ch);
};
};
39
4. EXERCICE
6- Ecrire la fonction qui permet d’afficher la liste entière à l’envers
Prototype de la fonction : afficher_envers(GrandNombre Nb);
afficher_envers(GrandNombre Nb) {
Element *p, *q, *r;
p=Nb.Debut; q=p->suivant; r=q->suivant;
q->suivant=p;
while (r!= NULL) {
p=q; q=r;
r=r->suivant;
q->suivant=p;
}
Nb.Fin=Nb.Debut;
Nb.Debut=q;
afficher(Nb);
}
40
4. EXERCICE
7- Ecrire la fonction main() dont on trouve la lecture de deux grands
nombres (ch1 et ch2) et l’affichage du résultat de leurs somme
main(){
printf("Donner un très grand nombre : "); gets(ch1);
printf("Donner un très grand nombre : "); gets(ch2);
initialisation (&Nombre1); Convertir(&Nombre1, ch1);
initialisation (&Nombre2); Convertir(&Nombre2, ch2);
initialisation (&Nombre3);
if (Nombre1.Npaquets<=Nombre2.Npaquets) somme(Nombre1,
Nombre2, &Nombre3);
else somme(Nombre2, Nombre1, &Nombre3);
printf(" la somme = \n");
afficher_envers(Nombre3);
system("pause");
}
41