Académique Documents
Professionnel Documents
Culture Documents
PREMIERE PARTIE
1
Listes
◼ listes hétérogènes :
◼ les éléments sont de types différents
2
Principes des TDA
fonctions
◼ l'utilisateur ne voit que les services (l’interface) pas
la représentation interne
3
Les types de données
abstraits (TDA)
◼ définition :
◼ un ensemble de données organisé pour que les
◼ encapsulation
◼ vérification de types
4
Incarnation d'un TDA
◼ définition :
une incarnation (une réalisation, une mise en œuvre,
une « implémentation ») d'un TDA est
◼ la déclaration de la structure de données
5
Les éléments d’une
liste:
6
Stockage direct
◼ Définition
◼ Un conteneur est en stockage direct quand il
◼ Utilisation
◼ « Petits objets » en mémoire et facile à copier
7
Stockage indirect
◼ Définition
◼ Un conteneur est en stockage indirect quand il
8
TDA ELEMENT
◼ tous les éléments appartiennent à un TDA ELEMENT
qui possède un élément vide et sur lequel on peut :
◼ saisir un élément
◼ afficher un élément
◼ affecter un élément dans un autre élément
◼ copier les informations d’un élément dans un autre
élément (le dupliquer)
◼ comparer deux éléments
◼ allouer dynamiquement la mémoire ou initialiser un
élément
◼ libérer la mémoire allouée pour un élément
9
TDA ELEMENT
/***************************************************
* Fichier : ELTPRIM.H
* Contenu : Déclaration des primitives du TDA ELEMENT.
***************************************************/
#ifndef _ELTPRIM_H
#define _ELTPRIM_H
#include "ELTSDD.H"
/* Affectation du 2eme argument dans le 1er qui est donc modifié et passé par
adresse */
void elementAffecter(ELEMENT*, ELEMENT);
/* Libération de mémoire */
void elementDetruire (ELEMENT);
#endif 10
Remarque
11
Exemple 1: stockage
direct (entiers) (1)
/***************************************************
* Fichier : ELTINT.H
* Contenu : Déclaration de la structure de données adoptée
* pour une réalisation du TDA ELEMENT.
***************************************************/
#ifndef _ELTINT_H
#define _ELTINT_H
#endif
12
Exemple 1: stockage
direct (entiers) (2)
/********************************************************
* Fichier : ELTINT.C
* Contenu : Définition des primitives pour une réalisation par des
entiers du TDA ELEMENT.
********************************************************/
#include <stdio.h>
#include "ELTPRIM.H" ELEMENT est
définit dans
#define ELEMENT_VIDE 32767
ELTINT.H qui est
reconnu
ELEMENT elementCreer (void) { automatiquement
return ELEMENT_VIDE ;} dans ELTINT.C
13
Exemple 1: stockage
direct (entiers) (3)
14
Exemple 1: stockage
direct (entiers) (4)
15
Exemple 2: stockage
indirect (client) (1)
Le client est une structure :
➢ Nom
➢ Adresse
➢ cin
/*****************************************************
* Fichier : ELTCLT.H
* Contenu : Déclaration de la structure de données adoptée
* pour une réalisation du TDA ELEMENT par client.
*****************************************************/
#ifndef _ELTCLT_H
#define _ELTCLT_H
typedef struct
{
char nom[20];
char adresse[30];
int cin;
ELEMENT ici est un
} elem, *ELEMENT; pointeur sur une
structure
#endif
16
Exemple 2: stockage
indirect (client) (2)
/*************************************************
* Fichier : ELTCLT.C
* Contenu : Définition des primitives pour une réalisation par
des clients du TDA ELEMENT.
************************************************/
#include <stdio.h>
Ici on utilise malloc
#include <stdlib.h> et free car on est
#include <string.h> dans le stockage
#include "ELTPRIM.H" indirect (pointeurs)
17
Exemple 2: stockage
indirect (client) (3)
void elementLire(ELEMENT* elt) {
char x;
printf(" \nDonnez un nom svp :") ;
fgets((*elt)->nom, 18, stdin);
printf(" \nDonnez une adresse svp :") ;
fgets((*elt)->adresse, 18,stdin);
printf(" \nDonnez le numéro CIN :") ;
scanf("%d",&((*elt)->cin));
x=getchar();
}
18
Exemple 2: stockage
indirect (client) (4)
void elementAffecter(ELEMENT* e1, ELEMENT e2) {
*e1 = e2 ;
}
e1 @ cl1 ◼ e1: contient une adresse d’un client
ali ◼ *e1 est égal à @cl1
@ cl1 adr1 ◼ (*e1)->nom est égal à ali
10 ◼ (*e1)->adresse est égal à adr1
◼ (*e1)->cin est égal à 10
e2 ◼ e2: est une adresse d’un client
hamed ◼ e2->nom est égal à hamed
adr2 ◼ e2->adresse est égal à adr2
20 ◼ e2->cin est égal à 20
elementAffecter(&e1, e2)
e1 @ cl1 ◼ e1: contient une adresse d’un client
e2 ali ◼ *e1 est égal à e2
adr1 ◼ (*e1)->nom est égal à hamed
10 ◼ (*e1)->adresse est égal à adr2
◼ (*e1)->cin est égal à 20
e2
hamed
adr2
20 19
Exemple 2: stockage
indirect (client) (5)
int elementCopier(ELEMENT *e1, ELEMENT e2) {
strcpy((*e1)->nom, e2->nom);
strcpy((*e1)->adresse, e2->adresse);
(*e1)->cin = e2->cin;
}
e1 @ cl1 e1 @ cl1
ali hamed
@ cl1 adr1 @ cl1 adr2
10 20
e2 e2
hamed hamed
adr2 adr2
20 20
elementCopier(&e1, e2)
21
Remarque
◼ Afin d’établir le lien entre ELTPRIM.H et les
implémentations on utilise un fichier intermédiaire
ELTSDD.H qui va définir le fichier d’implémentation
◼ ELTSDD.H sera modifié quand on voudra changer la
représentation adoptée (entier, clients etc.)
/******************************************************
* Fichier : ELTSDD.H
* Contenu : Inclusion du fichier où est déclarée la structure
de données adoptée pour réaliser le TDA ELEMENT.
******************************************************/
#ifndef _ELTSDD_H
#define _ELTSDD_H
#include "ELTCLT.H"
ou
ELTINT.H
#endif
22
/* ELTSDD.h sera modifié
quand on voudra changer la
Schéma général
représentation adoptée
(entier string etc.)*/
ELTSDD.h
ou
include
ELTPRIM.h
entiers …
ELTINT.h ….
ELTINT.c ….
23
L’implantation des
listes en C
un tableau)
◼ Listes chaînées
24
Primitives du TDA
LISTE
/*****************************************************************
* Fichier : LSTPRIM.H
* Contenu : Déclaration des primitives du TDA LISTE
******************************************************************/
#ifndef _LSTPRIM_H
#define _LSTPRIM_H
Toutes les
#include "ELTPRIM.H"
primitives des
#include "LSTSDD.H"
éléments
peuvent êtres
LISTE listeCreer(void);
utilisées
void listeDetruire(LISTE);
int estVide(LISTE);
int estSaturee(LISTE);
int listeTaille(LISTE);
ELEMENT recuperer(LISTE, int);
int inserer(LISTE, ELEMENT,int);
int supprimer(LISTE, int);
void listeAfficher(LISTE);
LISTE listeCopier(LISTE);
int listeComparer(LISTE, LISTE);
#endif
25
Implémentation
contiguë
26
Implémentation
contiguë (en C)
◼ une liste contiguë est un pointeur sur
une structure à deux champs
◼ un tableau qui contient les éléments de la liste
(éléments) : la première case est vide afin
d’éviter le décalage entre les positions et les
indices
◼ un entier indiquant l'indice du dernier élément de
la liste (lg) =taille logique
L éléments 0 %
1 a
2 b
3 c
...
100 @
lg 3
27
Exemple: liste en
stockage direct
◼ Liste d’entiers
◼ Chaque case de la liste contient un entier
L éléments 0 %
1 123
2 34
3 5
4 67
...
...
100 @
lg 4
28
Exemple: liste en
stockage indirect
◼ Liste de clients
◼ Chaque case de la liste contient l’adresse
d’une structure client (pointe sur un client)
L ali
éléments 0 %
@ cl1 adr1
1 @ cl1 10
2 @ cl2 hamed
@ cl3 @ cl2 adr2
3
@ cl4 20
4
salah
...
@ cl3 adr3
...
30
100 @
karim
lg 4 @ cl4 adr4
40
29
Déclaration de la
structure
/***************************************************
* Fichier : LSTTAB.H
* Contenu : Déclaration de la strucure de données pour réaliser
* le TDA LISTE PAR TABLEAU
***************************************************/
#ifndef _LSTTAB_H
#define _LSTTAB_H
#include "ELTPRIM.H"
typedef struct {
ELEMENT elements[LongMax]; /* tableau automatique */
int lg; /* taille logique de la liste */
} laStruct,*LISTE;
#endif
30
Remarques
31
Implémentation des
primitives
/******************************************************
* Fichier : LISTAB.C
* Contenu : Définition des primitives pour une réalisation
* par tableau du TDA LISTE.
******************************************************/
#include <stdlib.h>
#include <stdio.h>
#include "LSTPRIM.H"
LISTE listeCreer(void) {
LISTE L;
L = (LISTE) malloc(sizeof(laStruct));
if(!L) {
printf(" \nProblème de mémoire") ;
exit(0) ;
}
L->lg = 0;
return(L);
}
free(L);
} 32
Insertion
int inserer (LISTE L, ELEMENT e, int pos) {
int i;
int succee=1;
if (estSaturee(L)){
printf ("\nListe saturée");
succee=0;}
else {
if ((pos < 1) || (pos > L->lg + 1)) {
printf ("\nPosition invalide");
succee=0;
}
else {
for(i = L->lg; i>= pos; i--)
elementAffecter(&L->elements[i+1],
L->elements[i]);
elementAffecter(&L->elements[pos], e);
(L->lg)++;
}
}
return(succee);
} 33
Exemple Insertion
(stockage direct)
Insérer (77) à la position 2
L éléments 0 %
1 123
2 34
3 5
4 67
...
...
100 @
lg 4
34
Exemple Insertion
(stockage direct)
Insérer (77) à la position 2
elementAffecter(&L->elements[5], L->elements[4]);
L éléments 0 %
1 123
2 34
3 5
4 67
5 67
...
100 @
lg 4
35
Exemple Insertion
(stockage direct)
Insérer (77) à la position 2
elementAffecter(&L->elements[4], L->elements[3]);
L éléments 0 %
1 123
2 34
3 5
4 5
5 67
...
100 @
lg 4
36
Exemple Insertion
(stockage direct)
Insérer (77) à la position 2
elementAffecter(&L->elements[3], L->elements[2]);
L éléments 0 %
1 123
2 34
3 34
4 5
5 67
...
100 @
lg 5
37
Exemple Insertion
(stockage direct)
Insérer (77) à la position 2
elementAffecter(&L->elements[2], 77);
(L->lg)++;
L éléments 0 %
1 123
2 77
3 34
4 5
5 67
...
100 @
lg 5
38
Exemple Insertion
(stockage indirect)
L ali
éléments 0 % @ cl1 adr1
10
1 @ cl1
hamed
2 @ cl2
@ cl2 adr2
3 @ cl3 20
4 @ cl4 salah
... @ cl3 adr3
... 30
100 @ karim
@ cl4 adr4
lg 4 40
saber
@ cl5 adr5
50 39
Exemple Insertion
(stockage indirect)
Insérer (saber, adr5, 50) à la position 2
elementAffecter(&L->elements[5], L->elements[4]);
la 5eme case du tableau reçoit @ cl4 (pointe sur le client à l’adresse @ cl4)
L ali
éléments 0 % @ cl1 adr1
10
1 @ cl1
hamed
2 @ cl2
@ cl2 adr2
3 @ cl3 20
4 @ cl4 salah
5 @ cl4 @ cl3 adr3
... 30
100 @ karim
@ cl4 adr4
lg 4 40
saber
@ cl5 adr5
50 40
Exemple Insertion
(stockage indirect)
Insérer (saber, adr5, 50) à la position 2
elementAffecter(&L->elements[4], L->elements[3]);
la 4eme case du tableau reçoit @ cl3 (pointe sur le client à l’adresse @ cl3)
L ali
éléments 0 % @ cl1 adr1
10
1 @ cl1
hamed
2 @ cl2
@ cl2 adr2
3 @ cl3 20
4 @ cl3 salah
5 @ cl4 @ cl3 adr3
... 30
100 @ karim
@ cl4 adr4
lg 4 40
saber
@ cl5 adr5
50 41
Exemple Insertion
(stockage indirect)
Insérer (saber, adr5, 50) à la position 2
elementAffecter(&L->elements[3], L->elements[2]);
la 3eme case du tableau reçoit @ cl2 (pointe sur le client à l’adresse @ cl2)
L ali
éléments 0 % @ cl1 adr1
10
1 @ cl1
hamed
2 @ cl2
@ cl2 adr2
3 @ cl2 20
4 @ cl3 salah
5 @ cl4 @ cl3 adr3
... 30
100 @ karim
@ cl4 adr4
lg 4 40
saber
@ cl5 adr5
50 42
Exemple Insertion
(stockage indirect)
Insérer (saber, adr5, 50) à la position 2
elementAffecter(&L->elements[2], @ cl5 );
la 3eme case du tableau reçoit @ cl5 (pointe sur le client à l’adresse @ cl5)
(L->lg)++;
L ali
éléments 0 % @ cl1 adr1
10
1 @ cl1
hamed
2 @ cl5
@ cl2 adr2
3 @ cl2 20
4 @ cl3 salah
5 @ cl4 @ cl3 adr3
... 30
100 @ karim
@ cl4 adr4
lg 5 40
saber
@ cl5 adr5
50 43
Suppression
if (estVide(L)) {
printf ("\nListe vide");
succee=0;}
else {
if ((pos < 1) || (pos > L->lg)) {
printf (“\nPosition invalide");
succee=0;}
else {
elementDetruire(L->elements[pos]);
for(i=pos;i<=L->lg;i++)
elementAffecter(&L->elements[i],
L->elements[i+1]);
(L->lg)--;
}
}
return(succee);
}
44
Récupérer
ELEMENT recuperer(LISTE L, int pos) {
LISTE LR = listeCreer();
int i;
ELEMENT elt;
46
Copier (2)
Si on utilise elementAffecter au lieu de elementCopier
alors pour les listes qui contiennent des éléments en
stockage indirect on aura:
L LR
@ cl1
éléments ali éléments
adr1
0 % % 0
10
1 @ cl1 @ cl1 1
@ cl2 @ cl2 @ cl2
2 2
hamed
3 @ cl3 @ cl3 3
adr2
4 @ cl4 20 @ cl4 4
... ...
@ cl3
... ...
salah
100 @ adr3 @ 100
30
lg 4 4 lg
@ cl4
karim
adr4
40 47
Comparaison
return test;
}
48
listeAfficher, estVide,
estSaturee, listeTaille
void listeAfficher(LISTE L) {
int i;
for(i = 1; i <= L->lg; i++)
elementAfficher(L->elements[i]);
}
int estVide(LISTE L) {
return (L->lg == 0);
}
int estSaturee(LISTE L) {
return (L->lg == LongMax);
}
int listeTaille(LISTE L) {
return (L->lg);
}
49
Remarque
◼ Afin d’établir le lien entre LSTPRIM.H et les
implémentations on utilise un fichier intermédiaire
LSTSDD.H qui va définir le fichier d’implémentation
◼ LSTSDD.H sera modifié quand on voudra changer la
représentation adoptée (chaînée, contiguë etc.)
/************************************************
* Fichier : LSTSDD.H
* Contenu : Inclusion du fichier où est déclarée la structure
* de données adoptée pour réaliser le TDA LISTE.
************************************************/
#ifndef _LSTSDD_H
#define _LSTSDD_H
#include "LSTTAB.H"
#endif
Ou
LSTPTR.H
50
/* LSTSDD.h
Schéma général
sera modifié quand on voudra
changer la représentation
adoptée (chainée- contigue
etc.)*/
LSTSDD.h
ou
include
LSTPRIM.h
contiguë chainée
LSTTAB.h LSTPTR.h
(structure) (structure)
ELTPRIM.h
….
LSTTAB.c LSTPTR.c
51
L’utilisation: exemple
/********************************************
* Fichier : main.c
* Contenu : Test du TDA LISTE
********************************************/
#include <stdio.h>
#include "ELTPRIM.H"
#include "LSTPRIM.H"
int main()
{
int i;
ELEMENT elt;
LISTE L = listeCreer();
53
Création du projet
sous Visual C++
54
Remarques
◼ C++, JAVA, ADA sont conçus pour supporter la
réalisation de TDA
◼ en C comme vous avez constaté, utiliser les TDA
c'est assez acrobatique et même contre nature
◼ pourquoi le langage C ?
◼ le plus répandu
◼ impensable encore de se dire informaticien en
sans maîtriser le C
◼ mettre en œuvre les TDA en C vous permettra
de maîtriser le C mais aussi de mieux
comprendre les problèmes résolus par C++ (ou
java) et d'accepter de payer le prix de la
complexité technique des langages orientés
objets pour obtenir une plus grande sécurité de
programmation.
55