Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Cours Algo

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 32

UNIVERSITE PAUL SABATIER TOULOUSE III

Algorithmique, Structures de donn ees et langage C

L3 IUP AISEM/ICM
Janvier 2005

J.M. ENJALBERT

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Chapitre 1

Rappels et compl ements de C


1.1 Structures

Une structure rassemble des variables, qui peuvent etre de types di erents, sous un seul nom ce qui permet de les manipuler facilement. Elle permet de simplier l ecriture dun programme en regroupant des donn ees li ees entre elles. Un exemple type dutilisation dune structure est la gestion dun r epertoire. Chaque che dun r epertoire contient (par exemple) le nom dune personne, son pr enom, son adresse, ses num eros de t el ephone, etc... Le regroupement de toutes ces informations dans une structure permet de manipuler facilement ces ches. Autre exemple: On peut repr esenter un nombre complexe a ` laide dune structure. On d enit une structure a ` laide du mot-cl e: struct suivi dun identicateur (nom de la structure) et de la liste des variables quelle doit contenir (type et identicateur de chaque variable). Cette liste est d elimit ee par des accolades. Chaque variable contenue dans la structure est appel ee un champ ou un membre. D enir une structure consiste en fait a ` d enir un nouveau type. On ne manipulera pas directement la structure de la m eme mani` ere que lon ne manipule pas un type. On pourra par contre d enir des variables ayant pour type cette structure. Exemple: struct complexe { double reel; double imag; }; struct complexe x,y; Dans cet exemple, on d enit une structure contenant deux r eels puis on d eclare deux variables ayant pour type struct complexe. Les op erations permises sur une structure sont laectation (en consid erant la structure comme un tout), la r ecup eration de son adresse (op erateur &) et lacc` es a ` ses membres. On acc` ede a la valeur dun membre dune structure en faisant suivre lidenticateur de la variable de type structure par un point suivi du nom du membre auquel on souhaite acc eder. Par exemple x.reel permet dacc eder au membre reel de la variable x. On peut initialiser une structure au moment de sa d eclaration, par exemple: struct complexe x={10,5}; On peut d enir des fonctions qui renvoie un objet de type structure. Par exemple, la fonction suivante renvoie le complexe conjugu e de x: struct complexe conjugue(struct complexe x); { struct complexe y; 1

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

y.reel=x.reel; y.imag=-x.imag; return y; } Lutilisation de cette fonction pourra ressembler a `: struct complexe x,z; z=conjugue(x); Laectation revient a ` aecter chaque membre de la structure, par exemple: struct complexe x,z; x=z; est equivalent a `: struct complexe x,z; x.reel=z.reel; x.imag=z.imag;

1.2

Types synonymes

Le langage C permet de cr eer de nouveaux noms de types de donn ees grace a ` la fonction typedef. Par exemple: typedef int longueur fait du nom longueur un synonyme de int. La d eclaration: longueur l est alors equivalente a ` int l. eer deux Autre exemple, la d eclaration typedef struct complexe comp,*p comp permet de cr nouveaux mot-cl es: comp equivalent a ` struct complexe et p comp equivalent a ` struct complexe* (pointeur de struct complexe). Attention, un typedef ne cr ee pas de nouveaux types mais simplement de nouveaux noms pour des types existants.

1.3
1.3.1

Pointeurs typ es
Pr esentation

A une variable correspond un emplacement m emoire caract eris e par une adresse et une longueur (par exemple 4 octets cons ecutifs pour un long int). Cest, bien sur, le compilateur qui assure la gestion de la m emoire et aecte a ` chaque variable un emplacement d etermin e. On peut acc eder a la valeur de cette adresse grace a ` lop erateur unaire & dit op erateur dadressage. Un pointeur est une variable dun type sp ecial qui pourra contenir ladresse dune autre variable. On dit quil pointe vers cette variable. Celui-ci devra aussi conna tre le type de la variable vers laquelle il pointe puisque la taille dune variable (en octets) d epend de son type. La d eclaration dun pointeur devra donc indiquer le type dobjet vers lequel il pointe (on dit dun pointeur quil est typ e). La syntaxe est la suivante: type *identificateur; Par exemple, pour d eclarer un pointeur vers un entier on ecrira: int* p_entier; ou encore: int *p_entier; 2

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

On peut r ealiser des op erations sur des pointeurs de m eme type. On peut en particulier aecter a ` un pointeur un autre pointeur du m eme type ou ladresse dune variable de m eme type que celle du pointeur. On acc` ede a la valeur stock ee a ` ladresse contenue dans un pointeur grace a ` lop erateur unaire dit de r ef erencement ou dindirection: * Dans lexemple suivant: int a; int* p_a; p_a=&a; *p a et a font r ef erence au m eme emplacement m emoire (et ont donc la m eme valeur). Un pointeur peut par ailleurs pointer vers un autre pointeur. On peut aussi incr ementer un pointeur. Cel` a revient a ` augmenter sa valeur de la taille de lobjet point e et donc a ` pointer sur lobjet suivant du m eme type (sil en existe un!). La d eclaration dun pointeur alloue un espace m emoire pour le pointeur mais pas pour lobjet point e. Le pointeur pointe sur nimporte quoi au moment de sa d eclaration. Il est conseill e dinitialiser tout pointeur avant son utilisation eective avec la valeur NULL (constante pr ed enie qui vaut 0) ce qui, par convention, indique que le pointeur ne pointe sur rien.

1.3.2

Pointeurs et tableaux

La d eclaration dun tableau r eserve de la place en m emoire pour les el ements du tableau et fournit une constante de type pointeur qui contient ladresse du premier el ement du tableau. Cette constante est identi ee par lidenticateur donn e au tableau (sans crochets). Cest cette constante de type pointeur qui va permettre de manipuler facilement un tableau en particulier pour le passer en param` etre dune fonction puisquon ne passera a ` la fonction que ladresse du tableau et non tous ses el ements. Lexemple suivant: int tab[10]; d eclare un tableau de 10 el ements. tab contient ladresse du premier el ement et donc lexpression: tab == &tab[0] est VRAIE. On a donc de m eme: *tab == tab[0] tab[1] == *(tab+1) tab[k] == *(tab+k) Les deux ecritures sont autoris ees. La di erence entre un tableau et un pointeur est quun tableau est une constante non modiable alors quun pointeur est une variable.

1.3.3

Passage de param` etres ` a une fonction

On a vu que les param` etres pass es a ` une fonction le sont par valeur et ne peuvent pas etre modi es par lex ecution de la fonction. Ceci est tr` es contraignant si lon souhaite quune fonction renvoie plusieurs r esultats. Par exemple, si lon souhaite ecrire une fonction permuttant deux entiers, le code suivant qui parait correct ne fonctionnera pas: void permutation(int a, int b) { int c; c=a; a=b; b=c; } 3

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Lappel de la fonction: permutation(x,y); naura ainsi aucun eet sur x et sur y. La solution consiste a ` passer, pour les param etres que lon souhaite voir modier par la fonction, non plus les valeurs de ces param` etres mais les valeurs des adresses de ces param` etres. Les param` etres de la fonction devront donc etre des pointeurs. On acc` edera aux valeurs propement dites a ` lint erieur de la fonction gr` ace a ` lop erateur dindirection *. Si lon reprend lexemple pr ec edent, cela donne: void permutation(int* p_a, int* p_b) { int c; c=*p_a; *p_a=b; *p_b=c; } Remarque: on aurait pu garder les identicateurs initiaux a et b! Et lappel devra se faire en passant en param` etres les adresses des variables a ` modier gr` ace a ` lop erateur dadressage &: permutation(&x,&y);

1.3.4

Allocation dynamique

La d eclaration de variables dans la fonction main ou globalement r eserve de lespace en m emoire pour ces variables pour toute la dur ee de vie du programme. Elle impose par ailleurs de conna tre avant le d ebut de lex ecution lespace n ecessaire aux stockage de ces variables et en particulier la dimension des tableaux. Or dans de nombreuses applications le nombre d el ements dun tableau peut varier dune ex ecution du programme a ` lautre. La biblioth` eque stdlib fournit des fonctions qui permettent de r eserver et de lib erer de mani` ere dynamique (` a lex ecution) la m emoire. La fonction qui permet de r eserver de la m emoire est malloc 1 Sa syntaxe est: void* malloc(unsigned int taille) La fonction malloc r eserve une zone de taille octets en m emoire et renvoie ladresse du d ebut de la zone sous forme dun pointeur non-typ e (ou NULL si lop eration nest pas possible). En pratique, on a besoin du type dun pointeur pour pouvoir lutiliser. On souhaite dautre part ne pas avoir a ` pr eciser la taille de la m emoire en octets surtout sil sagit de structures. Lusage consiste donc pour r eserver de la m emoire pour une variable dun type donn ea `: D eclarer un pointeur du type voulu. Utiliser la fonction sizeof(type) qui renvoie la taille en octets du type pass e en param` etre. forcer malloc a ` renvoyer un pointeur du type d esir e. Par exemple, pour r eserver de la m emoire pour un entier, on ecrira: int* entier; entier=(int*) malloc(sizeof(int)); Ceci est surtout utilis e pour des tableaux, par exemple pour un tableau de N complexe (cf. le paragraphe sur les structures) on ecrirai: struct complexe * tabcomp; tabcomp=(struct complexe*) malloc(N*sizeof(struct complexe)); La fonction free() permet de lib erer la m emoire pr ec edemment r eserv ee. Sa syntaxe est: void free(void* p)
1. il existe aussi la fonction calloc assez similaire et donc superu...

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Ainsi, dans le second exemple on ecrirai: free(tabcomp);

1.4

Pointeurs g en eriques

En C, les pointeurs comme les autres variables sont typ es. Par exemple un pointeur dentiers: int *p est di erent dun pointeur de r eels float *p m eme si chacun dentre eux contient une adresse en m emoire. Ceci permet au compilateur de conna tre le type de la valeur point ee et de la r ecup erer (cest lop eration de d er ef erencement). C ne permet les aectations entre pointeurs que si ceux-ci sont de m eme type. Pour ecrire des fonctions ind ependantes dun type particulier (par exemple une fonction de permutation) le m ecanisme de typage peut etre contourn e en utilisant des pointeurs g en eriques. Pour cr eer un pointeur g en erique en C, il faut le d eclarer de type void*.

1.4.1

Copie de zones m emoires

Lutilisation de pointeurs g en eriques ne permet pas dutiliser lop erateur de d er ef erencement * et donc dacc eder au contenu dune variable. Ceci pose un probl` eme si lon veut copier des donn ees dune variable d esign ee par un pointeur g en erique vers une autre. La librairie string.h fournit une fonction qui permet de r esoudre ce probl` eme: memcpy(): Syntaxe: void *memcpy(void *pa, void *pb, unsigned int N) Copie N octets de ladresse pb vers ladresse pa et retourne pa. Lexemple qui suit illustre lutilisation de cette fonction.

1.4.2

Exemple

Si lon nutilise pas des pointeurs g en eriques, il faut ecrire autant de versions de la fonction permutation que de types de variables a ` permutter: Pour des entiers: void permut_int(int *p_a, int *p_b) { int c; c=*p_a; *p_a=*p_b; *p_b=c; } et pour des r eels: void permut_float(float *p_a, float *p_b) { float c; c=*p_a; *p_a=*p_b; *p_b=c; } Que lon utilisera de la mani` ere suivante: int i=2,j=3; float x=3.4,y=6.5; permut_int(&i,&j); permut_float(&x, &y); 5

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Pour pouvoir utiliser la m eme fonction quel que soit le type des donn ees a ` manipuler il est n ecessaire de passer en param` etre la taille des donn ees a ` traiter qui d epend de leurs types. La fonction de permutation g en erique peut s ecrire: void permut(void* p_a, void* p_b, int taille) { void* p_c; p_c=malloc(taille); memcpy(p_c,p_a,taille); /* *p_c=*p_a nest pas autoris e */ memcpy(p_a,p_b,taille); memcpy(p_b,p_c,taille); free(p_c); } Que lon pourra utiliser ainsi: int i=2,j=3; float x=3.4,y=6.5; permut(&i,&j, sizeof(i)); permut(&x, &y, sizeof(x)); On rapelle que la fonction sizeof() renvoie la taille correspondant au type de la variable pass ee en param` etre. Remarquez que cette fonction reste valable pour des structures complexes. Par exemple: struct complexe { double reel; double imag; }; struct complexe cx={1,2}, cy={3,4}; permut(&cx, &cy, sizeof(cx));

1.5

Pointeurs de fonctions

Les pointeurs de fonction sont des pointeurs qui, au lieu de pointer vers des donn ees, pointent vers du code ex ecutable. La d eclaration dun pointeur de fonction ressemble a ` celle dune fonction sauf que lidenticateur de la fonction est remplac e par lidenticateur du pointeur pr ec ed e dun ast erisque (*) le tout mis entre parenth` eses. Exemple: int (* p_fonction) (int x, int y); d eclare un pointeur vers une fonction de type entier n ecessitant deux param` etres de type entier. Lint er et est, par exemple, de pouvoir passer en param` etre dune fonction, une autre fonction. Utilisation: int resultat; int calcul(int x, int y) { ... 6

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

} p_fonction=calcul; resultat=p_fonction(3,5); /* Equivalent a ` resultat=calcul(3,5) */

1.5.1

Exemple complet

Recherche du minimum dune fonction monovariable y=f(x) entre 2 bornes (Algorithme plut ot simpliste!): #include <stdio.h> /*-------------------------------------------------------*/ float carre(float x) { return x*x; } /*-------------------------------------------------------*/ float parabole(float x) { return x*x-4*x+2;; } /*-------------------------------------------------------*/ float min_fct(float a, float b, float (* pF) (float x)) { int i; float pas; float vmin; float valeur; pas=(b-a)/100; vmin=pF(a); for (i=1; i<101; i++) { valeur=pF(a+i*pas); if (vmin > valeur) vmin=valeur; } return vmin; } /*-------------------------------------------------------*/ int main() { printf("%f \n",min_fct(-3.0,3.0,carre)); printf("%f \n",min_fct(-3.0,3.0,parabole)); return 0; }

1.6
1.6.1

Compilation s epar ee et classes dallocation de variables


Variables locales et globales

Variables locales ou internes Les variables dites locales sont celles qui sont d eclar ees dans un bloc (s eparateurs: { et } ). Elles ne sont visibles (donc utilisables) que dans ce bloc. Leur dur ee de vie va de lex ecution du d ebut de 7

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

bloc jusqu` a la n du bloc (variables volatiles). Variables globales ou externes Ce sont les variables d eclar ees hors de tout bloc. Elles sont visibles a ` partir de leur d enition. Exemple #include <stdio.h> double x; int N; /* Variables globales */

double f1() { int N; /* variable locale qui masque la variable globale de m^ eme nom */ int i; /* autre variable locale */ ... x=...; /* Utilisation de la variable globale x (d econseill e) */ } int main() { /* dans le main, x et N sont accessibles mais pas i */ }

1.6.2

D enition et d eclaration

La d enition dune variable eectue une r eservation de m emoire. Ex: int N La d eclaration fait r ef erence a ` une d enition. Elle neectue pas de r eservation en m emoire, la variable doit avoir et e d enie par ailleurs. Ex: extern int N

1.6.3

Variables communes

Un programme C, d` es quil devient un peu important, est constitu e de plusieurs chiers sources. Le partage des variables entre les di erents chiers n ecessite certaines pr ecautions. Une variable globale commune a ` plusieurs chiers doit etre d enie dans un seul chier et d eclar ee dans tous les chiers qui doivent y avoir acc` es. Ex: chier1.c: int N; chier2.c: extern int N;

1.6.4

Classe dallocations de variables

Une variable est d enie par sa classe dallocation qui peut etre: extern, auto, static, register. Par d efaut (sans pr ecision) les variables sont de classe auto. Pour d enir une variable dans une autre classe, il faut le pr eciser en t ete de d enition. Le tableau suivant r esume les caract eristiques de ces 4 classes. Classe auto static register extern M emoire pile (volatile) permanente registres permanente 8 Type locale locale locale globale

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Une variable locale peut etre allou ee en m emoire permanente si elle est d enie de classe static. Elle reste visible uniquement dans le bloc o` u elle est d enie. Exemple: int f() { static int N=0; /* allou ee et initialis ee au premier appel de la fonction*/ ... N++; /* compte le nombre dappels de la fonction */ } La d eclaration dune fonction poss` ede aussi une classe: Elle peut etre de classe static. Cel` a signie quelle nest visible (appelable) que dans le chier o` u elle est d enie. Elle peut etre de classe extern. Cel` a signie quelle est d enie dans un autre chier (seule sa d eclaration apparait).

1.6.5

Fichiers dent etes

Les chiers dent etes dextension .h regroupent les d eclarations de types, de fonctions et de variables exportables cest a ` dire suceptibles d etre utilis ees dans plusieurs chiers sources. En g en eral, on cr ee un chier dent ete .h pour chaque chier source .c (except e pour le chier contenant la fonction main). Le chier source contient les d eclarations des fonctions (ent ete+code) et des variables globales. Le chier dent ete contient les d enitions des fonctions et variables partageables. Exemple: chier: complexe.h struct s_comp { float reel; float imag; } typedef struct s_comp t_comp extern t_comp(J); extern t_comp sommme(t_comp, t_comp); extern t_comp produit(t_comp, t_comp); ... chier: complexe.c #include "complexe.h" t_comp J={0,1}; t_comp somme(t_comp a, t_comp b) { t_comp c; c.reel=a.reel+b.reel; c:imag=a.imag+b.imag; return c; } ... 9

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Utilisation: chier prog.c #include "complexe.h" int main() { t_comp x={3,2},z; z=somme(x,J); ... return 0; } Compilation: gcc -Wall -o prog prog.c complexe.c

10

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Chapitre 2

Algorithmes
2.1 Notion dalgorithme

Un algorithme est une suite de traitements el ementaires eectu es sur des donn ees en vue dobtenir un r esultat en un nombre nis dop erations. Traitement el ementaire: traitement pouvant etre eectu e par un ordinateur. Notion relative. Exemple: le calcul de la racine carr ee dun nombre peut etre consid er e comme el ementaire en C en utilisant la biblioth` eque math ematique. Il ne lest pas pour un microcontroleur programm e en assembleur. Exemple: lalgorithme dEuclide calculant le PGCD de deux entiers: Soit la division euclidienne de a par b, a = bq + r. Lalgorithme dEuclide est bas e sur le principe que les diviseurs communs de a et b sont les m emes que ceux de b et r. En rempla cant a par b et b par r et en divisant a ` nouveau, on obtient deux entiers ayant les m emes diviseurs que les entiers a et b dorigine. Finalement, on obtient deux entiers divisibles entre eux (r = 0) dont le plus petit est le PGCD de a et de b.

2.2

Repr esentation des algorithmes

Un programme est la r ealisation dun algorithme. Pour saranchir dun langage de programmation particulier, di erentes techniques de repr esentation sont utilis ees.

2.2.1

Pseudo langage

Permet de repr esenter formellement un algorithme ind ependamment de limpl ementation (langage). Bas e sur les instructions disponibles dans la plupart des langages. Structures el ementaires: Entr ees/Sorties: LIRE, ECRIRE aectation: X Y instruction conditionnelle: SI condition ALORS instructions SINON instructions FIN SI r ep etition TANT QUE condition FAIRE instructions FIN TANT QUE POUR i=0 A n FAIRE instructions FIN POUR FAIRE instructions TANT QUE condition 11

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Exemple: calculer la factorielle de N (version it erative): LIRE N F 1 POUR I=1 A N FAIRE F F I FIN POUR ECRIRE F Il nexiste pas de formalisme universel. Chaque auteur a ` sa syntaxe particuli` ere.

2.2.2

Organigramme

Un organigramme permet de repr esenter graphiquement un algorithme. Exemple pour le calcul de la factorielle:
Lire N

F < 1

I < 1

I<=N Oui F < F*I

Non

I=I+1

Ecrire F

Fig. 2.1 Exemple dorganigramme En pratique cette repr esentation devient vite illisible pour des probl` emes complexes.

2.3

Analyse et complexit e dun algorithme

Il existe souvent plusieurs algorithmes permetant de r esoudre un m eme probl` eme. Exemple: les algorithmes de tri. Le choix du meilleur algorithme implique une analyse de ses performances. En g en eral, le crit` ere le plus important est celui du temps n ecessaire a ` son ex ecution. Celui ci d epend le plus souvent de la quantit e de donn ees a ` traiter. Par exemple, le temps n ecessiare pour trier un ensemble dobjets d epend du nombre dobjets. L etude de la complexit e dun algorithme consiste essentiellement a ` evaluer la d ependance entre le temps d ex ecution et le volume de donn ees 1 . Les r esultats sexpriment de mani` ere qualitative: On cherche par exemple a ` savoir si la complexit e croit de mani` ere lin eaire ou polynomiale avec le volume n de donn ees.
1. On peut aussi sint eresser a ` la quantit e de m emoire n ecessaire

12

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Par exemple, la recherche dun el ement particulier dans un ensemble de n el ements non tri es consiste a ` examiner chaque el ement jusqu` a trouver celui que lon cherche. Dans le meilleur cas, cela prendra une seule comparaison, dans le pire des cas, il faudra eectuer n comparaisons. En moyenne on aura n/2 comparaisons a ` eectuer. On sint eresse en g en eral a la complexit e dun algorithme: dans le meilleur cas, en moyenne, dans le pire des cas. On exprime la complexit e dun algorithme en ne gardant que le terme variant le plus avec n et en omettant les termes constants. Par exemple, un algorithme n ecessitant 100n 3 + 1000n2 + 5000n + 3 10000 instructions el ementaires sera dit de complexit e O(n ). Un algorithme ne d ependant pas du volume de donn ees sera dit de complexit e O(1). En g en eral un algorithme de complexit e O(n log n) sera plus ecace quun algorithme de complexit e O(n2 ) mais ceci peut n etre vrai que si n est assez grand. En eet la complexit e mesure le comportement asymptotique dun algorithme quand n tend vers linni. Le tableau suivant donne quelques exemples de complexit e que lon retrouve couramment. Soit E un ensemble de n donn ees: Algorithme Acc es au 1er el ement de E Recherche dichotomique (E tri e) Parcours de E Tri rapide Parcours de E pour chaque el ement dun ensemble F de m eme dimension G en eration de tous les sous-ensembles de E G en eration de toutes les permutations de E Complexit e O(1) O(log n) O(n) O(n log n) O(n2 ) O(2n ) O(n!)

Le tableau suivant donne les ordres de grandeurs des di erentes complexit es en fonction de la taille de lensemble de donn ees: Complexit e n=1 n=4 n=16 n=64 n=256 n=4096 O(1) 1 1 1 1 1 1 O(log n) 0 2 4 6 8 12 O(n) 1 4 16 64 256 4096 O(n log n) 0 8 64 384 2048 49152 O(n2 ) 1 16 256 4096 65536 16777216 O(2n ) 2 16 65536 18446744073709551616 O(n!) 1 24 20922789888000 En r esum e, la complexit e dun algorithme est la courbe de croissance des ressources quil requiert (essentiellement le temps) par rapport au volume des donn ees quil traite.

2.4

R ecursivit e

Une fonction r ecursive est une fonction qui sappelle elle-m eme. Exemple: calcul de la factorielle dun nombre. D enition it erative: n! = F (n) = n(n 1)(n 2)...2 1 Ce qui donne en C: long int fact(int N) { long int F=1; int i; for (i=1; i<=N; i++) 13

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

F=F*i; return F; } D enition r ecursive: F (n) = nF (n 1), F (0) = 1. Soit en C: long int factr(int N) { if (N==0) return 1; else return N*factr(N-1); } Si, en g en eral, la version r ecursive dun algorithme est plus el egante a ` ecrire que sa version it erative 2, elle est cependant plus dicile a ` mettre au point et moins ecace en temps calcul. Pour quun algorithme r ecursif fonctionne: il doit exister un cas terminal que lon est sur de rencontrer. Un m ecanisme de pile est par ailleurs n ecessaire. Il est naturel en C dans le passage de param` etres a ` une fonction.

2.5

Algorithmes de tri

Il sagit dun probl` eme classique (et utile) de lalgorithmique. On consid` ere un ensemble d el ements poss edant une relation dordre total (Exemple: entiers, r eels, caract` eres). On cherche a ` ordonner cet ensemble dans lordre croissant (ou d ecroissant).

2.5.1

Tri par s election

Principe Soit un ensemle de n el ements indic es de 0 a ` n-1. On suppose que les m premiers el ements (0 a m-1) sont tri es. On cherche la position k du plus petit el ement parmi les el ements m a ` n-1. On le permutte avec l el ement m. Lensemble se trouve donc tri e de lindice 0 a ` lindice m. On parcourt ainsi lensemble de l el ement m=0 a ` l el ement n-2. Illustration En gras, les el ements d ej` a tri es, en italique, les el ements a ` permutter.

18 2 2 2 2 2

10 10 3 3 3 3

3 3 10 9 9 9

25 25 25 25 10 10

9 9 9 10 25 18

2 18 18 18 18 25

2. On peut toujours transformer un algorithme r ecursif en algorithme it eratif

14

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Algorithme Soit a ` trier un tableau de N el ements (entiers), t[0] a ` t[N-1] POUR m=0 a N-2 FAIRE k p (indice du plus petit el ement entre t[m] et t[N-1]) SI k di erent de m ALORS permutter t[k] et t[m] FIN SI FIN POUR Programmation en C Le programme peut se d ecomposer en trois fonctions: une fonction de calcul de lindice du plus petit el ement entre t[m] et t[N-1], une fonction de permutation, La fonction de tri proprement dite. /* ------------------------ indice du plus grand e l ement entre m et n-1 */ int indice_min(int t[], int m, int n) { int i; int imin; imin=m; for (i=m+1; i<n; i++) if (t[i]<t[imin]) imin=i; return imin; } /* ------------------------------------------- permutation de 2 entiers */ void permutte(int *a, int *b) { int c; c=*a; *a=*b; *b=c; } /* -------------------------------------------------- tri par selection */ void tri_selection(int t[], int n) { int m; int p; for (m=0; m<N-1; m++) { p=indice_min(t,m,N); if (p!=m) permutte(&t[p],&t[m]); } } Analyse Cet algorithme n ecessite n2 /2 comparaisons et n permutations. Pour un nombre d el ements donn e, il eectue le m eme nombre dop erations que les el ements soient pratiquements d ej` a tri es ou totalement en d esordre. Sa complexit e est en O(n2 ). 15

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

2.5.2

Tri ` a bulle

Principe Le principe consiste a ` parcourir les el ements de lensemble de i=0 a ` n-1 en permuttant les el ements cons ecutifs non ordonn es. L el ement le plus grand se trouve alors en bonne position. On recommence la proc edure pour lensemble de i=0 a ` n-2 sauf si aucune permutation na et e n ecessaire a ` l etape pr ec edente. Les el ements les plus grands se d eplacent ainsi comme des bulles vers la droite du tableau.

2.5.3

Illustration

En italique, les deux el ements a ` comparer, en gras les el ements en bonne place. 18 10 10 10 10 10 3 3 3 3 3 3 3 3 3 2 Algorithme k N 1 FAIRE POUR i=0 a J-1 FAIRE SI t[i] > t[i+1] ALORS permutter t[i] et t[i+1] permutation=VRAI FIN SI FIN POUR TANT QUE permutation=VRAI Analyse Dans le pire des cas, le nombre de comparaisons et le nombre de permutations a ` eectuer sont de n2 /2. Dans le meilleur des cas (ensemble d ej` a tri e), le nombre de comparaisons est de n 1 et lalgorithme est donc de complexit e lin eaire. 10 18 3 3 3 3 10 10 10 10 10 9 9 9 2 3 3 3 18 18 18 18 18 18 9 9 9 10 2 2 9 9 25 25 25 25 9 9 9 9 18 2 2 2 10 10 10 10 9 9 9 9 25 2 2 2 2 18 18 18 18 18 18 18 2 2 2 2 2 25 25 25 25 25 25 25 25 25 25 25

2.5.4

Tri par insertion

Principe On prend 2 el ements et on les met dans lordre. On prend un troisi` eme el ement quon ins` ere dans les 2 el ements d ej` a tri es, etc.. 16

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Un el ement m va etre ins er e dans lensemble d ej` a tri e des el ements 0 a ` m-1. Ce qui donnera m+1 el ements tri es (0 a ` m). Linsertion consiste a chercher l el ement de valeur imm ediatement sup erieure ou egale a ` celle de l el ement a ` ins erer. Soit k lindice de cet el ement, on d ecale les el ements k a ` m-1 vers k+1 a ` m et lon place l el ement a ` ins erer en position k. Illustration En gras, l el ement a ` ins erer dans la partie tri ee du tableau. 18 10 3 3 3 2 Analyse Dans le pire des cas, le nombre de comparaisons et de n2 /2. Dans le meilleur des cas il est de N . Lalgorithme est de complexit e O(N 2 ) mais il est plus ecace que les deux pr ec edents si le tableau est en partie tri e. 10 18 10 10 9 3 3 3 18 18 10 9 25 25 25 25 18 10 9 9 9 9 25 18 2 2 2 2 2 25

2.6

Algorithmes de recherche dans un ensemble

Un probl` eme courant est la recherche dun el ement particulier dans un ensemble. La solution la plus simple consiste a ` parcourir lensemble des el ements jusqu` a trouver celui que lon cherche. Dans le cas ou lensemble de recherche est tri e, une solution plus ecace consiste a ` faire une recherche dichotomique. On peut aussi utiliser des tables de hachage. Le principe consiste a ` associer a ` chaque el ement de lensemble une cl e calcul e, cette cl e permettant un acc` es direct a ` un el ement. Le calcul de la cl e pour l el ement recherch e permet dy acc eder directement. On cr ee en g en eral un index contenant linformation sur lequel se fera la recherche.
Index Dupont Albert Durand Marcel Informations Nom: Dupont Prenom adresse tel Nom Albert Prenom adresse tel Nom Durand Prenom adresse tel Nom Marcel Prenom adresse tel

Fig. 2.2 Cr eation dun index

17

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

2.6.1

Recherche s equentielle

La recherche s equentielle consiste a ` parcourir chaque el ement de lensemble avec celui recherch e. En g en eral cette recherche se fait sur une information particuli` ere de l el ement ou dans une table dindex. Cette m ethode fonctionne que lensemble soit tri e ou non. Dans le meilleur cas, cela prendra une seule comparaison, dans le pire des cas, il faudra eectuer n comparaisons. En moyenne on aura n/2 comparaisons a ` eectuer. La complexit e de lalgorithme est donc en O(n).

2.6.2

Recherche dichotomique

Dans le cas ou lensemble est tri e par rapport a ` lindex sur lequel doit se faire la recherche (par exemple le nom pour un annuaire), un algorithme plus ecace que la simple recherche s equentielle peut etre utilis e. On compare l el ement recherch e avec celui du milieu de lensemble. Si cest le m eme, la recherche est termin e sinon cest quil est plus grand ou plus petit et on recommence en ne gardant que la moiti e de lensemble. On divise ainsi lensemble de recherche par deux a ` chaque it eration. La complexit e de lalgorithme est donc en O(log n).

2.6.3

Tables de hachage

Le hachage consiste a ` calculer une cl e h(x) (nombre entier) pour chaque el ement x. h(x) contient lendroit ou lon trouve x dans lensemble. Si lapplication est injective (une cl e unique par el ement), il sut de calculer la cl e de l el ement recherch e et, sil existe, on y acc` ede directement. Pour des cha nes de caract` eres S = s0 s1 s2 ...sl1 , on utilise par exemple la fonction: h(S ) = (s0 B l1 + s1 B l2 + ... + sl2 B + sl1 ) mod N Ou N est la taille de la table de hachage (on choisi un nombre premier) et B une puissance de 2. si est le code ASCII du caract` ere dindice i de la cha ne.
Clef 0 1 2 3 4 5 6 7 Dupont Albert Durand Informations Nom: Dupont Prenom adresse tel Nom Albert Prenom adresse tel Nom Durand Prenom adresse tel Nom Marcel Prenom adresse tel

Marcel

Fig. 2.3 Table de hachage En pratique, lunicit e de la cl e pour une entr ee est rarement r ealisable. On peut donc avoir plusieurs el ements ayant la m eme cl e. On parle de collision. Une m ethode simple de g erer les collisions et de les lister dans une table parall` ele.

18

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Chapitre 3

Structures de donn ees


3.1 Types de donn ees abstraits (TDA)

Un TDA est un ensemble de donn ees organis e de sorte que les sp ecications des objets et des op erations sur ces objets (interface) soient s epar ees de la repr esentation interne des objets et de de la mise en oeuvre des op erations. Exemple de TDA: le type entier muni des op erations +, , , %, /, >, <, <=, >=, == est un TDA. Une mise en oeuvre dun TDA est la structure de donn ees particuli` ere et la d enition des op erations primitives dans un langage particulier. Les avantages des TDA sont: prise en compte de types complexes. s eparation des services et du codage. Lutilisateur dun TDA na pas besoin de conna tre les d etails du codage. ecriture de programmes modulaires.

3.2

Piles

Une pile est un ensemble de donn ees auquelles on acc` ede dans lordre inverse ou on les a ins er ees (Last Input, First Ouput). On ne peut acc eder quau sommet de la pile. Les op erations (primitives) sur une pile sont les suivantes: empiler( el ement): rajoute un el ement sur la pile. d epiler: renvoie la valeur de l el ement au sommet de la pile et le supprime. vide: renvoie VRAI si et seulement si la pile est vide En informatique, une pile sert, par exemple, pour g erer les appels et retours de fonctions. Si au cours de lex ecution dune fonction A, la machine doit ex ecuter une fonction B, elle place au sommet de la pile dex ecution ladresse a ` laquelle la fonction A a et e interrompue puis ex ecute les instructions de la fonction B avant de reprendre lex ecution de A a ` ladresse contenue au sommet de la pile dex ecution. Ceci permet dimbriquer des fonctions sans limitation (th eorique) de profondeur. Les piles sont aussi utilis ees pour passer des param` etres a ` une fonction ou pour stocker des variables locales.

3.2.1

Exemple dutilisation: calcul en notation polonaise invers ee (notation postx e)

Une formule math ematique peut etre repr esent ee par une liste de lex` emes un lex` eme pouvant repr esenter: une valeur 19

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

un op erateur binaire un op erateur unaire une parenth` ese (ouvrante ou fermante) Exemple: 4 + 2 16 6

peut etre repr esent ee par la liste: {(, 4, +, 2, *, sqrt, (, 16, ), ), /, 6} on parle de forme inx e, les op erateurs binaires etant plac es entre leurs op erandes. Il existe aussi une forme pr ex ee ou chaque op erateur pr ec` ede ses op erandes: {/, +, 4, *, 2, sqrt, 16, 6} et une forme postx ee ou chaque op erateur vient apr` es son dernier argument: {4, 2, 16, sqrt, *, +, 6, /} Lint er et de cette derni` ere forme est quelle ne n ecessite pas lutilisation de parenth` eses. L evaluation de la formule postx ee peut etre r ealis ee de mani` ere simple en utilisant une pile et en suivant les r egles suivantes: On lit les lex` emes dans lordre de la liste: si l el ement de la liste est une valeur, la placer sur la pile. si l el ement de la liste est un op erateur unaire, appliquer lop erateur sur le sommet de la pile. si l el ement de la liste est un op erateur binaire, appliquer lop erateur sur les deux el ements de t ete de la pile. Ce qui peut se traduire par lalgorithme suivant utilisant les op erations primitives sur une pile: pour chaque e l ement de la liste: si e l ement=valeur empiler(valeur) si e l ement= op erateur unaire operation= el ement r esultat=op eration(depiler) empiler(r esultat) si e l ement= op erateur binaire op eration= el ement op erande1=d epiler op erande2=d epiler r esultat=op eration(op erande1, op erande2) empiler(r esultat) A la n, le sommet de la pile contient le r esultat de la formule. el ement 4 2 16 sqrt * + 6 / pile (sommet a ` droite) 4 42 4 2 16 424 48 12 12 6 2

3.2.2

Impl ementation des piles

La mani` ere la plus simple dimpl ementer une pile consiste a ` utiliser un tableau. La pile peut etre caract eris ee par lindice dans le tableau de son sommet et par une sentinelle permettant de g erer les d ebordements de la pile. 20

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

3.3

Files

Dans une le, les el ements sont ajout es en queue et supprim es en t ete (First Input First Ouput). Ils sont donc trait es dans lordre darriv ee. On retrouve les op erations suivantes comme pour les piles: ajouter: rajoute un el ement en queue de le. supprimer: renvoie la valeur de l el ement en t ete de la le et le supprime. vide: renvoie VRAI si et seulement si la le est vide Les les sont utilis ees, par exemple, dans les applications pilot ees par ev` enements. Les ev` enements (clavier, souris, ...) sont stock es dans une le par ordre darriv ee avant d etre trait es. On les utilise aussi pour simuler des les dattente.

3.4
3.4.1

Listes
G en eralit es

Une liste est un ensemble ni d el ements not ee L = e1 , e2 , ..., en o` u e1 est le premier el ement, e2 le deuxi` eme, etc... Lorsque n=0 on dit que la liste est vide. Les listes servent a ` g erer un ensemble de donn ees, un peu comme les tableaux. Elles sont cependant plus ecaces pour r ealiser des op erations comme linsertion et la suppression d el ements. Elles utilisent par ailleurs lallocation dynamique de m emoire et peuvent avoir une taille qui varie pendant l ex ecution. Lallocation (ou la lib eration) se fait el ement par el ement 1 . Les op erations sur une liste peuvent etre: Cr eer une liste Supprimer une liste Rechercher un el ement particulier Ins erer un el ement (en d ebut, en n ou au milieu) Supprimer un el ement particulier Permuter deux el ements Concat ener deux listes ... Les listes peuvent par ailleurs etre: simplement cha n ees doublement cha n ees circulaires (cha nage simple ou double)

3.4.2

Listes simplement cha n ees

Une liste simplement cha n ee est compos ee d el ements distincts li es par un simple pointeur. Chaque el ement dune liste simplement cha n ee est form ee de deux parties: un champ contenant la donn ee (ou un pointeur vers celle-ci) un pointeur vers l el ement suivant de la liste. Le premier el ement dune liste est sa t ete, le dernier sa queue. Le pointeur du dernier el ement est initialis ea ` une valeur sentinelle, par exemple la valeur NULL en C. Pour acc eder a ` un el ement dune liste simplement cha n ee, on part de la t ete et on passe dun el ement a ` lautre a ` laide du pointeur suivant associ ea ` chaque el ement. En pratique, les el ements etant cr ees par allocation dynamique, ne sont pas contigus en m emoire contrairement a ` un tableau. La suppression dun el ement sans pr ecaution ne permet plus dacc eder
1. Un tableau peut aussi etre d eni dynamiquement mais pour modier sa taille, il faut en cr eer un nouveau, transf erer les donn ees puis supprimer lancien.

21

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

tete (NULL)

queue donnee: pointeur:

Fig. 3.1 Liste simplement cha n ee aux el ements suivants. Dautre part, une liste simplement chain ee ne peut etre parcourue que dans un sens (de la t ete vers la queue). Exemple dimpl ementation sous forme dune structure en C: struct s_element { int donnee; struct s_element* suivant; }; typedef struct s_element t_element;

3.4.3

Listes doublement cha n ees

Les listes doublement cha n ees sont constitu ees d el ements comportant trois champs: un champ contenant la donn ee (ou un pointeur vers celle-ci) un pointeur vers l el ement suivant de la liste. un pointeur vers l el ement pr ec edent de la liste. Elles peuvent donc etre parcourues dans les deux sens.
tete (NULL)

donnee:

pointeur:

Fig. 3.2 Liste doublement cha n ee

3.4.4

Listes circulaires

Une liste circulaire peut etre simplement ou doublement cha n ee. Sa particularit e est de ne pas comporter de queue. Le dernier el ement de la liste pointe vers le premier. Un el ement poss` ede donc toujours un suivant.
tete

donnee:

pointeur:

Fig. 3.3 Liste circulaire simplement cha n ee

22

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

3.4.5

Op erations sur une liste

On ne d ecrira dans ce paragraphe que quelques op erations sur les listes simplement cha n ees. Insertion dun el ement Linsertion dun el ement dans une liste peut se faire: en t ete de liste en queue de liste nimporte ou (` a une position x e par un pointeur dit courant) Lexemple choisi est celui de linsertion nimporte o` u (apr` es l el ement r ef erenc e par le pointeur courant):

Avant insertion:
tete

queue

(NULL) courant

nouveau

Apres insertion:
tete

queue

(NULL) courant

nouveau

Fig. 3.4 Insertion Les op erations a ` eectuer sont (dans lordre!): allouer de la m emoire pour le nouvel el ement copier les donn ees faire pointer le nouvel el ement vers l el ement suivant de celui point e par courant (vers NULL sil ny a pas de suivant) faire pointer l el ement point e par courant vers le nouvel el ement Le cas ou la liste est vide (tete egal a ` NULL) doit etre trait ea ` part. Exemple dimpl ementation de la fonction dinsertion: void insertion(t_element** tete, t_element* courant, int data) { t_element* nouveau; nouveau=(t_element*) malloc(sizeof(t_element)); nouveau->donnee=data; if (courant!=NULL) { nouveau->suivant=courant->suivant; courant->suivant=nouveau; 23

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

} else /* insertion en tete ou liste vide */ { nouveau->suivant=*tete; *tete=nouveau; } } Suppression dun el ement
Avant suppression:
tete (NULL) precedent courant

Apres suppression:
tete (NULL) precedent courant

Fig. 3.5 Suppression Dans le cas dun liste simplement cha n ee, la fonction de suppression demande un peu de r eexion pour etre impl ement e. Par exemple, une fonction permettant de supprimer l el ement point e par courant pourrait avoir cette interface: void suppression(t_element** tete, t_element* courant) Le passage du pointeur de t ete par adresse est n ecessaire pour pouvoir le modier si la suppression rend la liste vide ou si l el ement a ` supprimer etait le premier de la liste. On doit dabord distinguer sil sagit du 1er el ement de la liste ou pas: if (courant!=*tete) /* pas le premier element */ Dans ce cas il faut chercher le pr ed ecesseur de courant. La liste etant simplement cha n ee, on na pas dautre solution que de faire un parcours depuis la t ete jusqu` a trouver le pr ec edent de courant. precedent=*tete; while (precedent->suivant!=courant) precedent=precedent->suivant; On peut alors r ecup erer le lien contenu dans le champ suivant de l el ement a ` supprimer: precedent->suivant=courant->suivant; Dans le cas ou cest le premier el ement que lon supprime, on modie simplement le pointeur de t ete: else /* suppression du 1er element */ *tete=courant->suivant; Enn, dans tous les cas on lib` ere la m emoire: free(courant);

24

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Noter que dans cette impl ementation, le pointeur courant devient un pointeur pendant au retour de la fonction. Ce probl` eme doit etre trait e au niveau de lappel de la fonction ou en modiant un peu limpl ementation de la fonction (pr ef erable!).

3.4.6

Exemple dutilisation

Une fois que les primitives de manipulation de la liste ont et e impl ement ees, lutilisation est relativement simple. Lexemple suivant utilise les deux primitives vues pr ec edemment (insertion et suppression). int main() { t_element* tete=NULL; t_element* courant=NULL; /* insertion dun premier element: liste: 1 */ insertion(&tete,courant,1); /* deuxieme apres le premier: liste: 1 2 courant=tete; insertion(&tete,courant,2); /* courant pointe sur 2. liste: 1 2 3 */ courant=courant->suivant; insertion(&tete,courant,3); /* courant pointe sur 2. liste: 1 2 4 3 */ insertion(&tete,courant,4); /* insertion en tete. liste: 5 1 2 4 3 */ insertion(&tete,NULL,5); /* suppression de lelement 1. liste: 5 2 4 3 */ courant=tete->suivant; suppression(&tete,courant); /* suppression de la tete. liste: 2 4 3 */ courant=tete; suppression(&tete,courant); return 0; } */

25

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Chapitre 4

Arbres binaires
4.1 Introduction

Un arbre est une structure compos ee de noeuds et de feuilles (noeuds terminaux) reli es par des branches. On le repr esente g en eralement en mettant la racine en haut et les feuilles en bas (contrairement a ` un arbre r eel).

Racine

Feuilles

Fig. 4.1 Exemple darbre

Le noeud A est la racine de larbre. Les noeuds E, I, J, M, L et H sont des feuilles. Les noeuds B, C, D, F, G et K sont des noeuds interm ediaires. Si une branche relie un noeud ni a ` un noeud nj situ e plus bas, on dit que ni est un anc etre de nj . Dans un arbre, un noeud na quun seul p` ere (anc etre direct). Un noeud peut contenir une ou plusieurs valeurs. La hauteur (ou profondeur) dun noeud est la longueur du chemin qui le lie a ` la racine.

4.2

Arbres binaires

Un arbre binaire est un arbre tel que les noeuds ont au plus deux ls (gauche et droit).

27

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

Fig. 4.2 Exemple darbre binaire

4.3

Arbres binaires de recherche

Un arbre binaire de recherche est un arbre binaire qui poss` ede la propri et e fondamentale suivante: tous les noeuds du sous-arbre de gauche dun noeud de larbre ont une valeur inf erieure ou egale a ` la sienne. tous les noeuds du sous-arbre de droite dun noeud de larbre ont une valeur sup erieure ou egale a ` la sienne. Exemple:
10

13

11

15

Fig. 4.3 Arbre binaire de recherche

4.3.1

Recherche dans larbre

Un arbre binaire de recherche est fait pour faciliter la recherche dinformations. La recherche dun noeud particulier de larbre peut etre d enie simplement de mani` ere r ecursive: Soit un sous-arbre de racine ni , si la valeur recherch ee est celle de la racine ni , alors la recherche est termin ee. On a ` trouv e le noeud recherch e. sinon, si ni est une feuille (pas de ls) alors la recherche est infructueuse et lalgorithme se termine. si la valeur recherch ee est plus grande que celle de la racine alors on explore le sous-arbre de droite cest a ` dire que lon remplace ni par son noeud ls de droite et que lon relance la proc edure de recherche a ` partir de cette nouvelle racine. 28

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

de la m eme mani` ere, si la valeur recherch ee est plus petite que la valeur de n i , on remplace ni par son noeud ls de gauche avant de relancer la proc edure.. Si larbre est equilibr e chaque it eration divise par 2 le nombre de noeuds candidats. La complexit e est donc en O(log2 n) si n est le nombre de noeuds de larbre.

4.3.2

Ajout dun el ement

Pour conserver les propri et es dun arbre binaire de recherche n ecessite de, lajout dun nouvel el ement ne peut pas se faire nimporte comment. Lalgorithme r ecursif dajout dun el ement peut sexprimer ainsi: soit x la valeur de l el ement a ` ins erer. soit v la valeur du noeud racine ni dun sous-arbre. si ni nexiste pas, le cr eer avec la valeur x. n. sinon si x est plus grand que v , remplacer ni par son ls droit. recommencer lalgorithme a ` partir de la nouvelle racine. sinon remplacer ni par son ls gauche. recommencer lalgorithme a ` partir de la nouvelle racine.

5<6

3 4

5>3

9 8 12 10

1 0

5>4

Fig. 4.4 Ajout de 5 dans larbre

4.3.3

Impl ementation

En langage C, un noeud dun arbre binaire peut etre repr esent e par une structure contenant un champ donn ee et deux pointeurs vers les noeuds ls: struct s_arbre { int valeur; struct s_arbre * gauche; struct s_arbre * droit; }; typedef struct s_arbre t_arbre; La fonction dinsertion qui permet dajouter un el ement dans larbre et donc de le cr eer de mani` ere a ` ce quil respecte les propri et es dun arbre binaire de recherche peut s ecrire ainsi: void insertion(t_arbre ** noeud, int v) 29

L3 IUP AISEM/ICM

Algorithmique et langage C

J.M. ENJALBERT

{ if (*noeud==NULL) /* si le noeud nexiste pas, on le cr ee */ { *noeud=(t_arbre*) malloc(sizeof(t_arbre)); (*noeud)->valeur=v; (*noeud)->gauche=NULL; (*noeud)->droit=NULL; } else { if (v>(*noeud)->valeur) insertion(&(*noeud)->droit,v); /* aller a droite */ else insertion(&(*noeud)->gauche,v); /* aller a gauche */ } } On peut noter par ailleurs que larbre qui sera construit d ependra de lordre dans lequel seront ins er ees les di erentes valeurs. En particulier, si les valeurs sont ins er ees dans un ordre croissnt on obtiendra un arbre compl` etement d es equilibr e, chaque noeud nayant quun ls droit (gauche si les valeurs sont dans un ordre d ecroissant).

30

Vous aimerez peut-être aussi