Vous êtes sur la page 1sur 52

1 de 52

Algorithmique
Structures de donnes

Florent Hivert
Ml : Florent.Hivert@lri.fr
Page personnelle : http://www.lri.fr/hivert
2 de 52

Algorithmes et structures de donnes

La plupart des bons algorithmes fonctionnent grce une mthode


astucieuse pour organiser les donnes. Nous allons tudier quatre
grandes classes de structures de donnes :
Les structures de donnes squentielles (tableaux) ;
Les structures de donnes linaires (liste chanes) ;
Les arbres ;
Les graphes.
Structures squentielles : les tableaux 3 de 52

Structures
squentielles : les
tableaux
Structures squentielles : les tableaux 4 de 52

Structure de donne squentielle (tableau)

En anglais : array, vector.

Dfinition
Un tableau est une structure de donne T qui permet de stocker
un certain nombre dlments T [i] reprs par un index i. Les
tableaux vrifient gnralement les proprits suivantes :
tous les lments ont le mme type de base ;
le nombre dlments stocks est fix ;
laccs et la modification de llment numro i est en temps
constant (1), indpendant de i et du nombre dlments
dans le tableau.
Structures squentielles : les tableaux 5 de 52

Tableau en C

On suppose dclar un type elem pour les lments.


Espace mmoire ncessaire au stockage dun lment exprim
en mots mmoire (octets en gnral) : sizeof(elem).

dfinition statique : elem t[taille];


dfinition dynamique en deux temps (dclaration, allocation) :
#include <stdlib.h>
elem *t;
...
t = (elem*) malloc(taille*sizeof(elem));
ladresse de t[i] est not t + i. Calcule par

Addr(t[i]) = Addr(t[0]) + sizeof(elem) i


Structures squentielles : les tableaux 6 de 52

Oprations de base

Hypothses :
tableau de taille max_taille allou
lments 0 i < taille max_taille initialiss

Retenir (Oprations de base)

accs au premier lment : (1)


accs llment numro i : (1)
accs au dernier lment : (1)
insertion dun lment au dbut : (taille)
insertion dun lment en position i : (taille i) O(taille)
insertion dun lment la fin : (1)
Structures squentielles : les tableaux 7 de 52

Problme de la taille maximum

On essaye dinsrer un lment dans un tableau o

taille = max_taille

Il ny a plus de place disponible.

Comportements possibles :
Erreur (arrt du programme, exception)
R-allocation du tableau avec recopie, cot : (taille)
Structures squentielles : les tableaux 8 de 52

R-allocation (2)

Problme : On ajoute 1 par 1 n lments.


On suppose que lon ralloue une case supplmentaire chaque
dbordement. Cot (nombre de copies dlments) :
n
X n(n + 1)
i= (n2 )
2
i=1

Note : si on alloue des blocs de taille b, en notant k = d bn e :

k
X k(k + 1)
bi = b (n2 )
2
i=1

La vitesse est divise par b mais la complexit reste la mme.


Structures squentielles : les tableaux 9 de 52

R-allocation par doublement de taille

Retenir (Solution au problme de la r-allocation)


chaque dbordement, on r-alloue dK max_taillee o K > 1 est
une constante fixe (par exemple K = 2).

Dbut : tableau 1 lment


la m-ime r-allocation, la taille du tableaux : K m
Pour un tableau n lments : m est le plus petit entier tel
que K m n, soit m = dlogK (n)e
Nombre de recopies dlments :
m1
X Km 1
C =n+ Ki = n + (n + K m )
K 1
i=1

Finalement le cot est (n).


Structures squentielles : les tableaux 10 de 52

Nombre moyen de copies


Selon la valeur de K , la constante de complexit varie de manire
importante. Nombre de recopies dlments :
m1
X Km 1 n K
C =n+ Ki = n + n+ =n
K 1 K 1 K 1
i=1

Quelques valeurs :

K 1.01 1.1 1.2 1.5 2 3 4 5 10


K
K 1 101 11 6 3 2 1.5 1.33 1.25 1.11

Interprtation :
Si lon augmente la taille de 10% chaque tape, chaque nombre
sera recopi en moyenne 11 fois.
Si lon double la taille chaque tape, chaque nombre sera en
moyenne recopi deux fois.
Structures squentielles : les tableaux 11 de 52

Bilan

Retenir (Nombre de copies)


Dans un tableau de taille n, cot de lajout dun lment dans le
pire des cas :

Cot en temps n, Cot en espace (K 1)n .

En, moyenne sur un grand nombre dlments ajouts :


K
Cot en temps , Cot en espace K .
K 1
On dit que lalgorithme travaille en temps constant amortis
(Constant Amortized Time (CAT) en anglais).
Structures squentielles : les tableaux 12 de 52

Compromis Espace/Temps

Quand K augmente, la vitesse augmente mais la place mmoire


gaspille ( (K 1)n) augmente aussi. Le choix de la valeur de K
dpend donc du besoin de vitesse par rapport au cot de la
mmoire.

Retenir
Cest une situation trs classique : dans de nombreux problmes, il
est possible daller plus vite en utilisant plus de mmoire.

Exemple : on vite de faire plusieurs fois les mme calculs en


stockant le rsultat.
Structures squentielles : les tableaux 13 de 52

En pratique . . .

On utilise void *realloc(void *ptr, size_t size);

Extrait des sources du langage Python


Fichier listobject.c, ligne 41-91 :
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
Variables Dynamiques et pointeurs 14 de 52

Variables Dynamiques
et pointeurs
Variables Dynamiques et pointeurs 15 de 52

Variables dynamiques et pointeurs

Rappel : une variable usuelle est caractrise par quatre proprits :


(nom, adresse, type, valeur)

Retenir
Une variable dynamique est anonyme :
(adresse, type, valeur) .
On y accde grce un pointeur.

Un pointeur p qui repre (ou pointe vers) une VD dadresse a et


de type T
est de type T (lire flche T ) ;
a pour valeur ladresse a de la VD.
Variables Dynamiques et pointeurs 16 de 52

Variables dynamiques et pointeurs

adresse type
les quatre proprits dune variable usuelle nom valeur

x T
schma pour le pointeur p qui repre la VD p a
a T
dadresse a, de type T et de valeur v
v

x T
le lien dynamique entre le pointeur p et la VD p
T
quil repre est illustr par une flche
v
Variables Dynamiques et pointeurs 17 de 52

Les pointeurs nuls

Retenir
Un pointeur p peut valoir NULL : il ne repre aucune VD.

T
schma pour le pointeur p de type T qui ne p NULL
repre aucune VD

T
laccs aucune VD pour le pointeur p de p
type T est illustr par une croix

NULL est une valeur commune tous les pointeurs, ceux du type
T comme ceux des autres types.
Variables Dynamiques et pointeurs 18 de 52

Taille des variables

La taille dune VD de type T est celle de toute variable de type T .

La taille dun pointeur est fixe lors de la compilation, elle ne


dpend pas du type T . Cest la principale limitation quand la
mmoire disponible dans une machine.
32 bits, espace adressable 4 Gio (gibioctets) 109 .
64 bits, espace adressable 16 Eio (exbioctets) 1018 .
Variables Dynamiques et pointeurs 19 de 52

Dbut de vie dune VD

Soit p une variable du type T .


Retenir
Durant lexcution du programme, laction dallocation
allouer(p)
provoque :
1 la cration dune nouvelle VD de type T et de valeur
indtermine, par rservation dune nouvelle zone de mmoire ;
2 laffectation p de ladresse de cette VD.

T T
p ? allouer(p) p
====== T
?
Variables Dynamiques et pointeurs 20 de 52

Utilisations

Soit p un pointeur du type T .

Retenir
Si p repre une VD, cette variable est note p.

T
la VD de type T et de valeur v repre par p p
T
est note p
p v

Toutes les oprations licites sur les variables et les valeurs de


type T sont licites sur la variable p et la valeur p.
Variables Dynamiques et pointeurs 21 de 52

Dure de vie dune VD


Une VD existe de linstant o elle a t cre la fin de lexcution
du programme, sauf si elle est explicitement dsalloue.

Retenir
Si le pointeur p repre une VD, laction de dsallocation
explicite
dsallouer(p)
met fin lexistence de la VD p et rend disponible lespace
mmoire quelle occupait.

Aprs laction de dsallocation, la valeur de p est indtermine.

T T
p dsallouer(p) p ?
T ========
v
Variables Dynamiques et pointeurs 22 de 52

Double allocation, fuite de mmoire


Attention ne pas perdre laccs aux VDs : par exemple, si on
excute deux allouer(p) la suite, on ne peut plus accder la
premire VD alloue :

T T
p p
T T
allouer(p)
? ====== ?
T
?

Sil nexiste pas dautre pointeur dessus, la mmoire de la VD en


rouge est perdue !

Note : certain langage (Java, Python, . . .) utilise un composant


particulier appel ramasse miettes (Garbage Collector en anglais)
pour rcuprer la mmoire ainsi perdue.
Variables Dynamiques et pointeurs 23 de 52

Double pointeur et dsallocation

Attention aux rfrences fantmes !

la suite de lexcution de laction dsallouer(p), la valeur des


ventuels autres pointeurs qui repraient p est indfinie.
T T
p p ?
T
dsallouer(p)
v ========
T T
q q

Chacune de ces valeurs constitue une rfrence au fantme


dune VD.
Variables Dynamiques et pointeurs 24 de 52

Variable dynamique en C

Retenir
Dclaration dun pointeur p de type T : T *p;
Allocation dune VD pointe par p :
p = (T *) malloc(sizeof(T)) ;
note : en cas dchec de lallocation malloc retourne NULL.
Accs la VD et sa valeur :
*p = ...; ... = (*p) + 1;
Dsallocation de la VD pointe par p :
free(p);
Variables Dynamiques et pointeurs 25 de 52

Les pointeurs en C

Retenir
Tout type de pointeur
supporte lopration daffectation =
peux tre utilis comme type de retour dune fonction
Note : ajout dun pointeur un entier (en cas de variable
dynamique multiple ; tableau)
Pour deux pointeurs de mme type :
test dgalit ==, de diffrence !=
Note : comparaison <,<=,>,>= (en cas de variable dynamique
multiple ; tableau)
Variables Dynamiques et pointeurs 26 de 52

Le programme :

char *p, *q

p = (char *) malloc(sizeof(char));
*p = A;
q = (char *) malloc(sizeof(char));
*q = B;
*p = *q;
printf("%i, %i\n", p == q, *p == *q);

affiche :

0, 1
Variables structures, enregistrements 27 de 52

Variables structures,
enregistrements
Variables structures, enregistrements 28 de 52

type structur

Il est souvent pratique de regrouper logiquement plusieurs variables


en une seule variable compose. On parle alors de structure ou
denregistrement.
Retenir
Un type enregistrement ou type structur est un type T de
variable v obtenu en juxtaposant plusieurs variables v1 , v2 , . . .
ayant chacune un type T1 , T2 , . . .
les diffrentes variables vi sont appeles champs de v
elles sont repres par un identificateur de champ
si v est une variable de type structur T possdant le champ
ch, alors la variable v .ch est une variable comme les autres :
(type, adresse, valeur)
Variables structures, enregistrements 29 de 52

Les types structurs en algorithmique

Syntaxe
Dclaration de type structur :

nom_de_type = structure:
nom_du_champ_1 : type_du_champ_1;
nom_du_champ_2 : type_du_champ_2;
...

Dclaration de variable structure :

v: nom_de_type;
Variables structures, enregistrements 30 de 52

Les types structurs en C

Syntaxe
Dclaration de type structur :

struct nom_de_struct {
nom_du_champ_1 : type_du_champ_1;
nom_du_champ_2 : type_du_champ_2;
...
};

Dclaration de variable structure :

struct nom_de_struct v;

Ou avec une dfinition de type :

typedef struct nom_de_struct nom_type;


nom_type v;
Variables structures, enregistrements 31 de 52

Exemple de dclaration de type structur

struct s_date {
char nom_jour[9]; // lundi, mardi, ..., dimanche
int num_jour; // 1, 2, ..., 31
int mois; // 1, 2, ..., 12
int annee;
}

struct s_date date = {"vendredi", 21, 10, 2011};


Variables structures, enregistrements 32 de 52

Utilisation des types structurs

On suppose dclares des variables v , w dun type structur.


On dispose donc de variables
v.nom_du_champ_i de type type_du_champ_i

Retenir
Toute opration valide sur une variable de type type_du_champ_i
est valide sur v.nom_du_champ_i.

De plus, laffectation v = w est valide. Elle est quivalente aux


affectations
v.nom_du_champ_1 = w.nom_du_champ_1
v.nom_du_champ_2 = w.nom_du_champ_2
...
Structures linaires : les listes chanes 33 de 52

Structures linaires :
les listes chanes
Structures linaires : les listes chanes 34 de 52

Ide

Une variable dynamique peut elle mme tre


ou contenir un pointeur !
Structures linaires : les listes chanes 35 de 52

Chanages dynamiques

Listes Dynamiques simplement chanes (LDSC)

le pointeur p repre la LDSC qui p a1 a2 a3


implante la suite ha1 , a2 , a3 i

Dans le schma, trois types sont distinguer :


le type des lments de la suite :
le type des pointeurs :
le type des lments de la liste dynamique,
composition des deux types prcdents :
Structures linaires : les listes chanes 36 de 52

Dclaration des types cellule et liste

Soit element le type des lments de la suite.

Retenir
Une liste chane est obtenue partir du type cellule dfinie par
cellule = structure:
val: element
next : ^cellule
liste = ^cellule

En C :
struct s_cell
{
element val;
struct s_cell * next;
};
typedef struct s_cell cell; // Cellule
typedef struct s_cell *list; // Liste Chane
Structures linaires : les listes chanes 37 de 52

Pointeur et structure

Syntaxe
Accs aux donnes dune liste chane :
VD pointe par lst : *lst
champ val de cell : cell.val
champ val de la VD pointe par lst :

(*lst).val ou le raccourci lst->val

invalide si lst vaut NULL


Structures linaires : les listes chanes 38 de 52

Revenons lexemple schmatis plus haut :


le pointeur p repre la LDSC qui p a1 a2 a3
implante la suite ha1 , a2 , a3 i
On a :
p 6= NULL ;
p val = a1 ;
p next 6= NULL ;
p next val = a2 ;
p next next 6= NULL ;
p next next val = a3 ;
p next next next = NULL.
Soit, en convenant de noter f p p rptitions de loprateur f :
p( next)k1 6= NULL, pour 1 k 3 ;
p( next)k1 val = ak , pour 1 k 3 ;
p( next)3 = NULL.
Structures linaires : les listes chanes 39 de 52

Deux dfinitions quivalentes des LDSC

Dfinition (LDSC dfinie itrativement)


La suite ha1 , a2 , . . . , an i est implante par la LDSC repre par le
pointeur p lorsque :
p( next)k1 6= NULL, pour 1 k n
p( next)k1 val = ak , pour 1 k n
p( next)n = NULL.

Dfinition (LDSC dfinie rcursivement)


La suite U est implante par la LDSC repre par le p lorsque :
soit U = hi et p = NULL ;
soit U est de la forme U = hai V avec :
p 6= NULL p val = a ;
la suite V est implante par la LDSC pointe par p next.
Structures linaires : les listes chanes 40 de 52

Les notions sur les suites finies passent aux listes dynamiques
quelles implantent : longueur, concatnation, position...
Calcul itratif :
int longueur(list lst) {
int k = 0;
list q = lst;
while (q != NULL) {
q = q->next; k++;
}
return k;
}
Calcul rcursif :
int longueur(list lst) {
if (lst == NULL) return 0;
else return 1 + longueur(lst->next);
}
Structures linaires : les listes chanes 41 de 52

Dfinition (mode de programmation constructif)


Dans le mode de programmation constructif (ou pure), les
oprations laissent intacts leurs arguments.

insertion en tte dune LDSC, en mode constructif :


au
lst a1 a2 an
dbut

lst a1 a2 an
la fin
res x

list insertion_en_tete(element x, list lst) {


list res = alloue_cellule();
res->val = x;
res->next = lst;
return res;
}
Structures linaires : les listes chanes 42 de 52

Dfinition (mode de programmation mutatif)


Dans le mode de programmation mutatif (ou avec mutation), ou
avec modification), les oprations modifient leurs arguments.
Il faut donc passer un pointeur ou une rfrence vers largument
modifier.
insertion en tte dune LDSC, en mode mutatif
au
plst lst a1 a2 an
dbut

plst lst a1 a2 an
la fin
tmp x

void insertion_en_tete(element x, list *plst) {


list tmp = alloue_cellule();
tmp->val = x;
tmp->next = *plst;
*plst = tmp;
}
Structures linaires : les listes chanes 43 de 52

insertion en queue dune LDSC, constructive, rcursive


au
lst a1 a2 an
dbut

lst a1 a2 an
la fin
res a1 a2 an x

list insertion_en_queue(element x, list lst) {


list res = alloue_cellule();
if (lst == NULL) {
res->val = x; res->next = NULL;
return res;
} else {
res->val = lst->val;
res->next = insertion_en_queue(x, lst->next);
return res
}
}
Structures linaires : les listes chanes 44 de 52

insertion en queue dune LDSC, mutative, itrative


au
plst lst a1 a2 an
dbut

plst lst a1 a2 an x
la fin cur
tmp

void insertion_en_queue(element x, list *plst) {


list tmp = alloue_cellule();
tmp->val = x; tmp->next = NULL;
if (*plst == NULL) *plst = tmp;
else {
list cur = *plst;
while (cur->next != null) cur = cur->next;
cur->next = tmp;
}
}
Structures linaires : les listes chanes 45 de 52

Technique : LDSC avec une fausse tte

le pointeur p repre la
lst a1 a2 an
LDSC avec une fausse
tte qui implante la suite
?
ha1 , a2 , . . . , an i

Intrts :
en mode avec mutation ;
vite davoir distinguer les cas de llment de tte ou de la
liste vide dans les oprations dinsertion et de suppression.
Structures linaires : les listes chanes 46 de 52

Technique : LDSC avec pointeurs de tte et de queue

pointeurs reprant
respectivement la tte et la
a1 a2 an
queue de la LDSC qui implante
la suite ha1 , a2 , . . . , an i

Intrts :
en mode avec mutation ;
ajout en queue sans parcours de la LDSC ;
concatnation sans parcours des LDSC.

dfinir, aprs la dclaration du type Liste, par :


struct s_list_tq {
struct s_cell *first, *last;
}
Structures linaires : les listes chanes 47 de 52

Technique : LDSC circulaire

a1

pointeur reprant la queue de la LDSC circulaire qui a2


implante la suite ha1 , a2 , . . . , an i

an

Intrts :
en mode avec mutation ;
ajout en queue et suppression en tte sans parcours de la
LDSC ;
concatnation sans parcours des LDSC.
Structures linaires : les listes chanes 48 de 52

Listes dynamiques doublement chanes (LDDC)

pointeurs reprant
respectivement la
tte et la queue de a1
a2 an
la LDDC qui
implante la suite
ha1 , a2 , . . . , an i

Intrts :
en mode avec mutation ;
marches avant et arrire ;
ajout en queue et suppression en tte sans parcours de la
LDDC ;
concatnation sans parcours des LDDC.
Structures linaires : les listes chanes 49 de 52

Listes dynamiques doublement chanes (LDDC) (2)

La structure peut tre dclare par :

struct s_cell
{
element val;
struct s_cell * next;
struct s_cell * prev;
};

struct s_lddc
{
struct s_cell * first;
struct s_cell * last;
};
Structures linaires : les listes chanes 50 de 52

Applications

Implantation des types de donnes abstraits :


piles (dernier entr - premier sorti)
files dattente (premier entr - premier sorti)
double-queues
ensembles, tables dassociations

Algorithmes de retour sur trace, essais/erreurs (backtracking)


Structures linaires : les listes chanes 51 de 52

Application : exemple dalgorithme essais/erreurs

Problme (liste de candidats)


On veux maintenir une liste ordonne de candidats
qui supporte les oprations suivantes :
1 choix dun candidat avec suppression dans la liste (chaque
candidat ne peux tre choisi quune seul fois)
2 retour en arrire par re-insertion du candidat sa place
pour choisir un autre candidat
Structures linaires : les listes chanes 52 de 52

Retour en arrire dans une LDDC

Liste des a b c
candidats ;
slection de b choix

choix->next->prev = choix->prev;
choix->prev->next = choix->next;

Suppression de a b c
b de la liste
choix

Le pointeur choix contient toute linformation ncessaire


pour revenir la position de dpart ; il suffit de faire :
choix->next->prev = choix;
choix->prev->next = choix;

Vous aimerez peut-être aussi