Académique Documents
Professionnel Documents
Culture Documents
Cours I133-Pr - Hssina
Cours I133-Pr - Hssina
Module I133 :
Structures de données
- cours -
Version : Octobre 2022
Badr HSSINA - Enseignant chercheur
b a d r. h s s i n a @ u n i v h 2 c . m a
Laboratoire d’Intelligence Machine ( LIM)
FST Mohammedia, Université Hassan II de Casablanca
struct
{
int numero ;
float taille, poids ;
char sexe ;
} pers1, pers2 ;
struct personne
{
int numero ;
float taille, poids ;
char sexe ;
} pers1, pers2 ;
typedef struct {
int numero ;
float taille, poids ;
char sexe ;
} Personne ; /* personne est le nom du type */
Personne pers1, pers2 ;
pers1.numero = 7234 ;
pers1.sexe = 'M' ;
pers1.taille = 1.67 ;
pers1.poids = 67.8 ;
7 int a;
a=7;
1B0 1B1 1B2 1B3 1B4 1B5 1B6 1B7 1B8
int * P;
1B2 P=&a;
mémoire
(*P).champ P->champ
Équivalent à
int main() {
return 0;
}
Allocation
mémoire
Allocation Allocation
stack heap dynamique
automatique
Pointeur NULL
qui pointe vers l’espace réservé échec de réservation
......
} Etudiant ;
Etudiant * p ;
p = (Etudiant *) malloc ( sizeof(Etudiant)) ;
p = (T *) malloc (sizeof(T));
sizeof(T) donne la taille de T en nombre d'octets (de Bytes).
On demande l'espace mémoire pour stocker *p et on dépose
l'adresse de *p dans p.
Cette affectation est représentée par le schéma suivant:
Si nous n'avons plus besoin d'un bloc de mémoire que nous avons
réservé, alors nous pouvons le libérer à l'aide de la fonction free de
la bibliothèque <stdlib.h>.
libère le bloc de mémoire désigné par le <Pointeur>; n'a pas d'effet si
le pointeur a la valeur NULL.
Si nous ne libérons pas explicitement la mémoire à l'aide free, alors
elle est libérée automatiquement à la fin du programme.
Exemple :
Exemple :
10 55 8 12 13 70
T 0 1 2 3 4 5
10 55 8 12 13 70
@100 @104 @108 @112 @116 @120
T 0 1 2 3 4 5
10 55 8 12 13 70
@100 @104 @108 @112 @116 @120
13
Elément d’une liste chaînée
?
@901
indice
4
Elément d’un tableau 13 4 est l’indice de la cinquième case
@116
L
10 55 8 12 13 70
@2589 @ 321 @ 898 @ 901 @ 352 @NULL
@ 058 @2589 @ 321 @ 898 @ 901 @ 352
0 1 2 3 4 5
type contenu;
struct element * suivant;
}ElementListe;
ElementListe * L;
Element *L ;
int contenu;
struct element * suivant;
}ElementListe;
ElementListe * L;
Cette opération doit être faite avant toute autre opération sur la liste.
La fonction
NE =AllouerNoeud();
NE->contenu=donnee;
L=NE;
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 52
Opérations sur les listes chaînées :
Insertion au début de la liste
Prototype de la fonction :
(1)
donnee NULL
suivant
Nouveau_Element /* NE */
NULL
Choisir une position dans la liste (l'insertion se fera après la position choisie)
Le pointeur suivant du nouvel élément pointe vers l'adresse sur laquelle pointe
le pointeur suivant d'élément courant.
(*)
donnee donnee donnee donnee
L
suivant suivant suivant suivant
(2)
(1) NULL
donnee
suivant
Nouveau_Element
Question : Ecrire une fonction qui permet de calculer la taille d’une liste
(retourner le nombre d’éléments de la liste).
(*)
donnee donnee donnee donnee
L
suivant suivant suivant suivant
(1) NULL
Elem_supp
(*)
donnee donnee donnee donnee donnee
L
suivant suivant suivant suivant suivant
(1) NULL
Elem_supp
donnee
(1)
suivant
(2)
L 10 55 8 12 13 70
@2589 @ 321 @ 898 @ 901 @ 352 @NULL
@ 058 @2589 @ 321 @ 898 @ 901 @ 352
La liste doublement chaînée peut être parcourue dans les deux sens, du
premier vers le dernier élément et/ou du dernier vers le premier élément.
type contenu;
struct element * suivant;
struct element * precedent;
}ElementListe;
ElementListe * L;
char donnee;
struct element * suivant;
struct element * precedent;
}ElementListe;
ElementListe * L;
A B C D E
char info[10];
struct element * suivant;
struct element * precedent;
}ElementListe;
ElementListe * L;
Cette opération doit être faite avant toute autre opération sur la liste.
La fonction
ElementListe * ins_dans_liste_vide (ElementListe * L, char *info){
ElementListe * NE;
NE =AllouerNoeud();
◦ strcpy(NE->info,info);
L=NE;
return L;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 86
Opérations sur les LDC :
Insertion au début de la liste
Prototype de la fonction :
ElementListe * ins_debut_liste (ElementListe * L, char * info);
precedent (1)
donnee
suivant
Nouveau_Element
courant->suivant=NE;
NE->precedent=courant;}
return L;}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données 92
Opérations sur les LDC :
Insertion ailleurs dans la liste
Prototype de la fonction :
ElementListe * ins_liste (ElementListe * L, char * info, int pos);
La position indiquée ne doit pas être le 1er élément. Dans ce cas il faut
utiliser la fonction d'insertion au début de la liste.
NE->suivant = courant->suivant;
NE->precedent = courant;
courant->suivant->precedent = NE;
courant->suivant = NE;}
return L;}
C'est la raison pour la quelle nous allons créer une seule fonction.
(*)
precedent precedent precedent precedent
L
donnee donnee donnee donnee NULL
NULL suivant suivant suivant suivant
(3)
(1)
Elem_supp
(*)
precedent precedent precedent precedent
L
donnee donnee donnee donnee
NULL
NULL suivant suivant suivant suivant
(1)
(2)
Elem_supp
(3)
(1)
Elem_supp
La fonction
/* détruire la liste */
ElementListe *detruire (ElementListe * L) {
Ajouter Extraire
Sommet
Chaque problème qui utilise cette démarche peut être simulé (dans sa résolution)
par les piles.
D D
C C E E
B B B B B
A A A A A
dépilé dépilé empilé(E) empilé(D)
Différentes représentations
Représentation dynamique
• listes simplement chaînées.
Représentation statique
• Un tableau et une variable globale indiquant le
sommet.
• Un enregistrement avec deux champs.
donnee
suivant
donnee
suivant
donnee
NULL
suivant
} Pile;
Pile * sommet;
Fonction
Pile * initialisation (Pile * sommet) {
sommet = NULL;
return sommet;
}
Algorithme de la fonction :
(2) donnee
(1) suivant
Nouveau_Element
donnee
Sommet
suivant
donnee
suivant
donnee
suivant
donnee
NULL
suivant
Algorithme de la fonction :
le pointeur supp_elem contiendra l'adresse du pointeur sommet.
Retrait
donnee (1) Elem_supp
Sommet
suivant
(2)
donnee
suivant
donnee
suivant
donnee
NULL
suivant
Tant que le sommet n'est pas nul dépiler l’élément le plus haut de la pile.
Fonction :
Pile * pile_clear(Pile * sommet)
{
while (sommet != NULL) sommet=depiler(sommet);
return sommet;
}
#define MAX 20
typedef struct{
char T[MAX];
int sommet;
} TPile;
TPile pile;
else { pile->T[pile->sommet] = x;
pile->sommet++;
}
{ char x;
else {
pile-> sommet--;
x=pile->T[pile->sommet];
return x;}
}
( (
( (
(
( ( ( (
#include <stdlib.h>
#define MAX 10
typedef struct {
char T[MAX];
int sommet;
} TPile;
TPile pile;
char exp[10];
int i=0;
scanf("%s",exp);
initialiser(&pile);
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
dans le bus
ar
Extraction av Insertion
Les serveurs d’impression, qui doivent traiter les requêtes dans l’ordre dans lequel
elles arrivent, et les insèrent dans une file d’attente (ou une queue);
Un algorithme de parcours en largeur utilise une file pour mémoriser les nœuds visités;
On utilise aussi des files pour créer toutes sortes de mémoires tampons(en anglais
buffers)
Etc.
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
156
Représentation
Différentes représentations
Représentation statique
Un vecteur qui représente la FILE F[Max] avec av et
ar deux variables globales indiquant la tête et
la queue de la file.
Un enregistrement avec trois champs.
Représentation dynamique
Listes simplement chaînées
ar
av
inserer(C) extraire(A)
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
159
Les opérations de base sur la File
initialisation : la file est vide au départ
ar 0 et av 0
Remarque : on n’a pas besoin dans ce cas de préciser la tête, elle est toujours au
début de la file
E indice=4 E E E E
D D D av=3
D D av=3 av=3
int F[MAX];
int av;
int nb; // nombre d’élément dans la file
} TFile;
file->F[indice] = x;
file->nb++;
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
164
Les opérations de base sur la File
void defiler(TFile *file, int *obj)
Extraction
30 15 6 2 Insertion
debut fin
} Element;
typedef struct {
Cette opération doit être faite avant toute autre opération sur la File.
Elle initialise le pointeur debut et fin avec le pointeur NULL, et la taille avec la valeur 0.
Fonction
File * initialisation (File * F) {
F->debut = NULL;
F->fin = NULL;
F->taille = 0;
return F;
}
Prototype de la fonction :
La fonction renvoie un pointeur de type File.
Algorithme de la fonction :
Déclaration d'élément(s) à insérer.
Allocation de la mémoire pour le nouvel élément.
Remplir le contenu du champ de données.
Mettre à jour des pointeurs
Mettre à jour la taille de la file.
fin
debut Nouveau_Element
(2) donnee
donnee donnee donnee donnee (1) suivant
suivant suivant suivant suivant
NULL
Element *nouveau_element;
nouveau_element=AllouerNoued();
nouveau_element->info= donnee;
F->taille++;
return F;
}
Algorithme de la fonction :
le pointeur supp_elem contiendra l'adresse du 1er élément (debut)
le pointeur debut pointera vers le 2ème élément (après la
suppression du 1er élément, le 2ème sera au début de la file)
la taille de la file sera décrémentée d'un élément
debut fin
(2)
Elem_supp
if (F->debut==NULL) return F;
elem_supp= F->debut;
free (elem_supp);
F->taille--; return F };
Algorithme de la fonction
il faut se positionner au debut de la file
En utilisant le pointeur suivant de chaque élément, la file est
parcourue du debut vers la fin
La condition d'arrêt est donnée par la taille de la file
Fonction :
void affiche (File * F) {
Element *courant; int i;
courant = F->debut;
for(i=1;i<=(F->taille);i++) {
printf(" %d\n", courant->info);
courant = courant->suivant; }
}
Pr. B.HSSINA badr.hssina@univh2c.ma Module I133: Structures de données
178
Opération de base sur les Files
Vider la file
Algorithme de la fonction
Fonction :
G1
G2
G3 G4
#define T1 3
#define T2 7
#define T3 10
#define T4 12
#define T5 15
typedef struct {
int code;
int type_serv;
}Client;
}Element;
typedef struct {
} File;
{ Client C;
printf("donner le code : ");
scanf("%d",&C.code);
do{
printf("donner le service dont tu as besoin {1,2,3,4,5} : ");
scanf("%d",&C.type_serv);
}while((C.type_serv<1)||(C.type_serv>5));
return C;
Dans les piles, un seul pointeur est utilisé. Il Dans les files, deux pointeurs différents sont
pointe vers le haut de la pile. utilisés pour les extrémités; la tète et la fin.
Dans les piles, le dernier objet inséré est le Dans les files, l’objet inséré en premier est le
premier à sortir. premier qui sera supprimé.
Les piles suivent l’ordre Last In First Out (LIFO) Les files suivent l’ordre First In First Out (FIFO)
Les opérations de pile s’appellent Empiler et Les opérations de file sont appelées Enfiler et
Dépiler. Défiler.
Les piles sont visualisées sous forme de Les files sont visualisées sous forme de
collections verticales. collections horizontales.
Un arbre, appelé aussi arbre N-aire, chaque nœud possède au maximum N nœuds.
66 66
21 70 50 21 70 50
32 43 88 32 43 88
Un arbre contient donc au moins un nœud : sa racine. Tous les autres nœuds
suivent directement ou indirectement la racine.
Un sous arbre est un arbre.
Exemple : 66
La racine de cet arbre contient 66 Sous arbre
Il est constitué de trois sous-arbres
A1 : de racine 21, est réduit à 21 21 70 50
21 70
50 Sous arbre
32 43 88 Feuille
♦ Pour connaître les suivants de chaque nœud, il suffit de voir leur indice
dans les cases ad-hoc du tableau.
66
Numéro [0] [1] [2] [3] [4] [5] [6]
Valeur 66 21 70 50 32 43 88
21 70 50 Suivant1 1 -1 4 5 -1 -1 -1
Suivant2 2 -1 -1 -1 -1
-1 -1 -1
Suivant3 3 -1 -1 6 -1 -1 -1
32 43 88
♦ Cette construction est compliquée à gérer, et de ce fait, elle n’est pas très utilisée.
66 ● ● ●
66 66
66
21 69
21 69
21 50
19 20 67 90
19 20 90
88 43 43 89
5 7 5 7
Arbre * ar; 9 2
● ● NULL ●
7 4 3
NULL NULL NULL NULL NULL NULL
1. Parcours en profondeur
♦ Pour ce type de parcours; on distingue entre 3 algorithmes récursifs simple permettent le
parcours en profondeur d’un arbre binaire : préfixé, infixé et postfixé.
♦ Tous les nœuds de l’arbre sont atteints branche par branche dans toute leur profondeur.
7 4 3
7 4 3
7 4 3
N°2 N°3
55
typedef struct noeud {
int valeur;
struct noeud * fg; 40 60
struct noeud * fd;
} Arbre;
22 48 57 78
Arbre * ar;
33
3 5 3 5 23
2 9
2 2 8 11
(*q)->valeur=R->valeur;
if (R->fg!=NULL) S->fd=R->fg;
else S->fd=NULL;
free(R);
}