Chapitre 5. Récursivité et listesmathinfo.univ-reims.fr/IMG/pdf/chap5-2.pdf · Algorithmique et...
Transcript of Chapitre 5. Récursivité et listesmathinfo.univ-reims.fr/IMG/pdf/chap5-2.pdf · Algorithmique et...
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Chapitre 5. Récursivité et listes
La récursivité :– permet une écriture plus claire des algorithmes ;– les algorithmes sont généralement plus courts ;– il est plus facile de prouver la terminaison et la correction ;– le calcul de la complexité est simplifié.
Les listes :– c’est un type de données naturellement récursif ;– la gestion de la mémoire est généralement dynamique ;– très utiles pour représenter des problèmes irréguliers.
M. KRAJECKI 1 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
1. La récursivité
Définition 1 (Récursivité) Une fonction (ou une procédure)�
est diterécursive, si pour la définir (écrire son algorithme), au moins une référence àelle même (un appel à
�) est utilisée.
Par exemple, il est possible de définir ��� ainsi :
� ����� et ��� �� ���������������������
int fact(int n) {
if (n==0) return 1 ;
else return n*fact(n-1) ;
}
M. KRAJECKI 2 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Récursivité terminale
Un autre exemple, la définition récursive du pgcd :
int pgcd(int a, int b) {
if (a==b) return a ;
else if (a>b) return pgcd(a-b,b) ;
else return pgcd(a, b-a) ;
}
Vous pouvez remarquer que dans les deux exemples précédents, l’appelrécursif est la dernière instruction exécutée. On parle dans ce cas de
récursivité terminale.
M. KRAJECKI 3 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Elimination de la récursivité terminale
Il est facile de rendre une fonction récursive terminale en une fonction nonrécursive.
Il suffit de simuler la récursivité par une boucle tant que.
La négation du test d’arrêt de la récursivité étant utilisée pour le test de laboucle tant que.
Voici par exemple, la fonction itérative fact :
int fact(int n) {
int f = 1;
while (n!=0) {
f=f*n ; n -= 1 ;}
return f ;}
M. KRAJECKI 4 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Recherche dichotomique
Voici un autre exemple de récursivité terminale.
int dicho(int t[], int binf, int bsup, int v) {
if (binf>bsup) return -1 ;
else {
int p = (binf+bsup)/2 ;
if (t[p]==v) return p ;
else if (t[p]>v) return dicho(t, binf, p-1, v);
else return dicho(t, p+1, sup, v);
}
}
M. KRAJECKI 5 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Récursivité non terminale et croisée
Quand, dans la définition d’une fonction récursive, l’appel récursif ne termine
pas la fonction, on parle de récursivité non terminale.
La suppression de la récursivité non terminale est plus délicate. Une pile estalors nécessaire pour mémoriser l’état de la mémoire avant l’appel récursif.
Quand une fonction A est définie à l’aide du fonction B, elle même définie à
l’aide de A, on parle de récursivité croisée.
La suppression de la récursivité croisée, comme pour la récursivité nonterminale, est généralement délicate.
M. KRAJECKI 6 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
2. Les listes simplement et doublement chainées
Définition 2 (Liste) Une liste est une succession de valeurs d’unmême type pour lesquelles un accès direct n’est pas fréquent.
Le type liste peut être défini récursivement :
������������� ��������������où
�����et
����������� ���
Remarque : si nous acceptons cette définition,��� �!���#"$�!�%�&�%���(')�
devraitêtre notée par
���)�!�*���#"$�*�+�%�&�%�*���(',�*���-�.�%�&�/�-�.
M. KRAJECKI 7 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Fonctions de base
Les actions de bases sur les listes sont définies par les 5 fonctionssuivantes :
1. Vide : 0 ��1 �32542. Tête : 0 ��1 � ��6�� �8792:13. Queue : 0 ��1 � ��6�� �879250 ��1 �4. ConsVide : 2;6�� �875. Cons : 1 �<0 ��1 �=2>0 ��1 �
Il est possible de montrer que tous les traitements sur les listes linéairespeuvent être écrits à l’aide de ces 5 primitives. Cependant, pour desproblèmes d’efficacité, il est parfois nécessaire d’étendre cet ensemble deprimitives.
M. KRAJECKI 8 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Comparaison entre listes et tableaux
La représentation des listes par chaînages est classique. Elle permet unegestion dynamique de la mémoire et de faciliter l’insertion et la suppressionde valeurs.
1 2 3 4
l:
insertion / suppression mémoire accès aléatoire
Tables mauvais (décalage) a priori mauvais bon
Listes rapide (chaînage) a priori bon mauvais
M. KRAJECKI 9 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Représentation par chaînage
Afin de représenter les listes par chaînages, nous allons définir la notion decellule. Une cellule comporte deux informations :– une valeur de la liste ;– un accès à la prochaine cellule de la liste ;Une liste est alors définie par l’accès à la première cellule qui la compose.
v1 v2 vn
l:
la première cellule une valeur l’accès à la prochaine cellule
l’accès à la première cellule
M. KRAJECKI 10 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Utilisation des structures et des pointeurs
En C, il existe un moyen de regrouper plusieurs valeurs dans unenregistrement (un bloc de mémoire contigüe). Voici un cours exemple quiregroupe deux entiers dans une structure :
struct deuxentiers {
int a ;
int b ;
};
main() {
struct deuxentiers v;
v.a = 5 ; v.b = 10;
printf("%d, %d\n", v.a, v.b);
}
M. KRAJECKI 11 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Utilisation des structures et des pointeurs
Pour représenter une cellule en C, l’utilisation de structures est conseillée.
Le deuxième champs de la structure (l’accès à la prochaine cellule) seradéfini comme un pointeur sur une cellule. Voici la définition en C d’unecellule pour une liste de caractères :
struct cellule {
char valeur ;
struct cellule *suivant ;
} ;
De même, une liste sera définie comme un pointeur sur une cellule...
M. KRAJECKI 12 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Exemple : définition d’une liste d’entiers
#include <stdlib.h>
#define VRAI !0
#define FAUX 0
#define BOOLEEN int
/* le type liste d’entiers */
typedef struct element {
int valeur ;
struct element *suivant ;
} element, * Liste ;
M. KRAJECKI 13 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Exemple : définition d’une liste d’entiers
/* Les fonctions de base */
BOOLEEN Vide(Liste L) {
return (L==NULL) ;
}
int Tete(Liste L) {
return L->valeur ;
}
Liste ConsVide() {
return NULL ;
}
M. KRAJECKI 14 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Exemple : définition d’une liste d’entiers
Liste Queue(Liste L) {
return L->suivant ;
}
Liste Cons(int V, Liste L) {
Liste tmp ;
tmp = (Liste) malloc(sizeof(element)) ;
tmp->valeur=V;
tmp->suivant=L;
return tmp ;
}
M. KRAJECKI 15 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Exemple : définition d’une liste d’entiers
Liste Saisie() {
int v=0; Liste l;
l=ConsVide();
printf("Valeur (-1 pour terminer) ?");
scanf("%d",&v);
while(v>=0) {
l=Cons(v,l);
printf("Valeur (-1 pour terminer) ?");
scanf("%d",&v);
}
return l;
}
M. KRAJECKI 16 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Exemple : définition d’une liste d’entiers
void Affiche(Liste L) {
if (Vide(L)) printf("()");
else {
printf("( %d, ", Tete(L));
Affiche(Queue(L)); printf(")");
}
}
/* un petit programme principal */
main() {
Liste maliste;
maliste=Saisie();
Affiche(maliste);
}
M. KRAJECKI 17 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
3. Représentation de polynômes creux par des listes
1. Représentation à l’aide de tableaux :
0 1 2 3 4
0 0 0 14 P(x) = x²+4
Pb :– nécessité de connaître la taille du polynôme le plus grand
– représentation à trou (par exemple� ��� � ���
���������).
2. Utilisation de listes :
4 0 1 2
coef coef degrédegré
P(x) = x²+4
P
M. KRAJECKI 18 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Définition du type + fonctions de base
Une cellule contiendra 3 informations : le degré du monome, le coefficient
associé et un lien sur le monome suivant.
2 fonctions en création :– Creation() : Polynome (création d’un nouveau polynôme) ;– ConsPoly(d : entier, c : reel, p : Polynome) :
Polynome.
4 fonctions de consultation :– PolyVide(p : Polynome) : Booleen ;– Coef(p : Polynome) : reel ;
– Degre(p : Polynome) : entier ;– Suivant(p : Polynome) : Polynome ;
M. KRAJECKI 19 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Manipulation des polynômes
1. Quelques fonctions simples :– affichage et saisie d’un polynôme : attention à l’ordre et aux doublons ;– longueur, evaluation et dérivation.
2. Tri d’un polynôme :– tri par insertion ;
– comment écrire efficacement une fonction d’insertion ?
3. Addition et multiplication de 2 polynômes triés :– algorithmes (un peu) plus complexes ;
– le tri est important : il simplifie le travail.
M. KRAJECKI 20 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Définition du type
#include <stdlib.h>
#include <math.h>
#define VRAI !0
#define FAUX 0
#define BOOLEEN unsigned char
typedef struct poly_nonvide {
float coef ;
int degre ;
struct poly_nonvide *suivant ;
} poly_nonvide, *Polynome;
M. KRAJECKI 21 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Les fonctions de base
BOOLEEN PolyVide(Polynome P){
return (P==NULL) ;
}
float Coef(Polynome P) {
return P->coef ;
}
int Degre(Polynome P) {
return P->degre ;
}
Polynome Suivant(Polynome P){
return P->suivant ;
}
M. KRAJECKI 22 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Les fonctions de base
Polynome Creation(){
return NULL ;
}
Polynome ConsPoly(int d, float c, Polynome P){
Polynome premier ;
premier = (Polynome) malloc(sizeof(poly_nonvide)) ;
premier->degre=d;
premier->coef=c;
premier->suivant=P;
return premier ;
}
M. KRAJECKI 23 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Affichage d’un polynôme
void Affiche(Polynome P){
if (!PolyVide(P)){
if (!PolyVide(Suivant(P))){
if (Coef(Suivant(P))>0)
printf("%f * x^%d + ", Coef(P), Degre(P));
else
printf("%f * x^%d ", Coef(P), Degre(P));
Affiche(Suivant(P));
}
else /* c’est le dernier monome */
printf("%f * x^%d.\n", Coef(P), Degre(P));
}
}
M. KRAJECKI 24 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Saisie d’un polynôme
Polynome Saisie() {
int d; float c;
printf("Degré du monome à ajouter
(-1 pour terminer) ?");
scanf("%d",&d);
if(d>=0) {
printf("Coef du monome à ajouter ?");
scanf("%f",&c);
return ConsPoly(d,c,Saisie());
}
else return Creation();
}
M. KRAJECKI 25 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Évaluation et dérivation d’un polynôme
Polynome Derive(Polynome P) {
if (PolyVide(P)) return Creation();
else if (Degre(P)>0)
return ConsPoly(Degre(P)-1, Degre(P)*Coef(P),
Derive(Suivant(P)));
else return Derive(Suivant(P));
}
float Evalue(float x, Polynome P) {
if (PolyVide(P)) return 0 ;
else return (Coef(P) * pow(x, Degre(P))
+ Evalue (x, Suivant(P)));
}
M. KRAJECKI 26 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Tri d’un polynôme
Polynome InsertionTriee(int d, float c, Polynome P){
if (PolyVide(P))
return ConsPoly(d,c,Creation());
else if (Degre(P)<d)
return ConsPoly(d,c,P);
else return ConsPoly(Degre(P), Coef(P),
InsertionTriee(d,c,Suivant(P)));
}
Polynome TriPoly(Polynome P){
if (PolyVide(P)) return Creation();
else return InsertionTriee(Degre(P), Coef(P),
TriPoly(Suivant(P)));
}
M. KRAJECKI 27 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Addition de deux polynômes
Polynome Addition(Polynome P1, Polynome P2) {
if (PolyVide(P1)) return P2 ;
else if (PolyVide(P2)) return P1 ;
else if (Degre(P1) > Degre(P2))
return ConsPoly(Degre(P1), Coef(P1),
Addition(Suivant(P1), P2));
else if (Degre(P2) > Degre(P1))
return ConsPoly(Degre(P2), Coef(P2),
Addition(P1, Suivant(P2)));
else if (Coef(P1)+Coef(P2)!=0)
return ConsPoly(Degre(P1), Coef(P1)+Coef(P2),
Addition(Suivant(P1),Suivant(P2)));
else return Addition(Suivant(P1),Suivant(P2));}
M. KRAJECKI 28 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Multiplication de deux polynômes
Polynome Multi(int d, float c, Polynome P) {
if (c==0) return Creation();
else if (PolyVide(P)) return Creation();
else return ConsPoly(d+Degre(P), c*Coef(P),
Multi(d,c,Suivant(P)));
}
Polynome Multiplication (Polynome P1, Polynome P2) {
if (PolyVide(P1)) return Creation();
else
return Addition(Multi(Degre(P1), Coef(P1), P2),
Multiplication(Suivant(P1),P2));
}
M. KRAJECKI 29 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Un petit programme principal
main(){
Polynome p1=Creation(),p2=Creation();
int choix=1; float x;
while(choix!=0) {
printf("1. Saisie du polynôme 1.\n");
printf("2. Saisie du polynôme 2.\n");
printf("3. Evaluation du polynôme 1.\n");
printf("4. Addition des 2 polynômes.\n");
printf("5. Multiplication des 2 polynômes.\n");
printf("Votre choix (0 pour quitter) ? ");
scanf("%d",&choix);
M. KRAJECKI 30 DESS IAS – Année 2003-2004
Algorithmique et programmation C Chap. 5 – Récursivité et listes
Un petit programme principal
switch(choix) {
case 1: {p1=Saisie(); Affiche(p1); break;}
case 2: {p2=Saisie(); Affiche(p2); break;}
case 3: {
printf("x="); scanf("%f",&x);
printf("P1(%f)=%f\n",x,Evalue(x,p1));
break;}
case 4: {Affiche(Addition(p1,p2));break;}
case 5: {Affiche(Multiplication(p1,p2));break;}
}
}
}
M. KRAJECKI 31 DESS IAS – Année 2003-2004