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.

Dnition
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 vrient gnralement les proprits suivantes : tous les lments ont le mme type de base ; le nombre dlments stocks est x ; laccs et la modication 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). dnition statique : elem t[taille]; dnition 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 n : (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

i=
i=1

n(n + 1) (n2 ) 2
n b

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


k

bi = b
i=1

k(k + 1) (n2 ) 2

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 K max_taille o K > 1 est une constante xe (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 = logK (n) Nombre de recopies dlments :
m1

C =n+
i=1

Ki = n +

Km 1 (n + K m ) K 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

C =n+
i=1

Ki = n +

n K Km 1 n+ =n K 1 K 1 K 1

Quelques valeurs : K
K K 1

1.01 1.1 1.2 1.5 2 3 4 5 10 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 : Cot en temps K , K 1 Cot en espace K .

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 che T ) ; a pour valeur ladresse a de la VD.

Variables Dynamiques et pointeurs

16 de 52

Variables dynamiques et pointeurs

les quatre proprits dune variable usuelle

adresse type nom valeur

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

T a v T

x le lien dynamique entre le pointeur p et la VD quil repre est illustr par une che p

T T v

Variables Dynamiques et pointeurs

17 de 52

Les pointeurs nuls


Retenir
Un pointeur p peut valoir NULL : il ne repre aucune VD.
schma pour le pointeur p de type T qui ne repre aucune VD T p NULL

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

T p

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 xe 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 ; laectation p de ladresse de cette VD.
T p ? T

== = ===

allouer(p)

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 est note p p p v T

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 n 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 n lexistence de la VD p et rend disponible lespace mmoire quelle occupait. Aprs laction de dsallocation, la valeur de p est indtermine.
T p v T T p

== = = ====

dsallouer(p)

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 p ? T p ? T ? T T

== = ===

allouer(p)

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 indnie.
T p v T q q T p ? T

== = = ====
T

dsallouer(p)

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 daectation = 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 dirence != 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); ache : 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 direntes variables vi sont appeles champs de v elles sont repres par un identicateur 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 dnition 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, laectation v = w est valide. Elle est quivalente aux aectations 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 implante la suite a1 , a2 , a3 p

a1

a2

a3

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 dnie 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 : champ val de cell : *lst 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 implante la suite a1 , a2 , a3 p a1 a2 a3

On a : p = NULL ; p val = a1 ; p next = NULL ; p next val = a2 ; p next next = 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 = 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 dnitions quivalentes des LDSC


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

Dnition (LDSC dnie rcursivement)


La suite U est implante par la LDSC repre par le p lorsque : soit U = et p = NULL ; soit U est de la forme U = a V avec :
p = 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 nies 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

Dnition (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 dbut la n res x lst lst a1 a1 a2 a2 an an

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

Dnition (mode de programmation mutatif)


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

la n

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 dbut la n res lst lst a1 a1 a1 a2 a2 a2 an an 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 dbut plst lst plst lst la n cur tmp a1 a1 a2 a2 an an x

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 LDSC avec une fausse tte qui implante la suite a1 , a2 , . . . , an

lst

a1 ?

a2

an

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 queue de la LDSC qui implante la suite a1 , a2 , . . . , an

a1

a2

an

Intrts : en mode avec mutation ; ajout en queue sans parcours de la LDSC ; concatnation sans parcours des LDSC. dnir, 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 implante la suite a1 , a2 , . . . , an a2

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 la LDDC qui implante la suite a1 , a2 , . . . , an

a1

a2

an

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) les 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) 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 candidats ; slection de b a choix b c

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

Suppression de b de la liste

a choix

Le pointeur choix contient toute linformation ncessaire pour revenir la position de dpart ; il sut de faire :
choix->next->prev = choix; choix->prev->next = choix;

Vous aimerez peut-être aussi