i=0 tant que i<n et t[i]≠x faire // on parcourt le tableau jusqu'à ce qu'on trouve x i=i+1 faitA la fin i vaut n si et seulement si x n'est pas dans le tableau.
x est dans le tableau | x n'est pas dans le tableau | |
nombre d'itérations | a | |
nombre moyen | ||
nombre maximal |
i=0 tant que i<n et t[i]<x faire // on parcourt le tableau jusqu'à ce qu'on trouve x ou un élément plus grand que x. i=i+1 fait si i<n et t[i]>x alors i=n // si x n'est pas dans tQuels sont le nombre moyen et le nombre maximal d'itérations de la boucle dans le cas où x est dans le tableau, et dans le cas où il n'y est pas ?
i=0 k=n tant que i+1<k faire // si x=t[a] alors a∈[i,k[ j=[(i+k)/2] // [i,k[=[i,j[ u [j,k[ si x<t[j] alors k=j // On remplace [i,k[ par [i,j[ sinon i=j // ou [j,k[ fait si i<k et t[i]≠x alors i=n // si x n'est pas dans tQuel est le nombre maximal d'itérations de la boucle ?
m=n tant que m>0 faire j=0 pour i=0,1,...,m-1 faire // parmi les m éléments du tableau à trier, on détermine la position i du plus grand si t[i]>t[j] alors j=i fait echanger t[m-1] et t[j] // on échange le plus grand et le dernier (Le plus grand est donc à sa place) m=m-1 // on fait comme si le tableau avait un élément de moins faitQuel est le nombre maximal d'itérations de la boucle interne ?
pour i=2, 3, ..., n faire // on initialise toutes les cases du tableau t à 1 t[i]=1 fait pour i=2, 3, ..., n faire si t[i]=1 alors // si i est premier j=i*i tant que j≤n faire t[j]=0 // on met 0 dans chacune des cases dont l'indice j est un multiple de i compris entre i2 et n. j=j+i fait finsi faitExécuter cet algorithme à la main pour n=30. Combien de fois l'instruction j=j+i est-elle effectuée? Montrer que son temps de calcul est en Θ(n ln(ln(n))). Que se passe-t-il si on enlève le test "si t[i]=1" ?
pour i=2, 3, ..., n faire t[i]=1 fait pour i=2, 3, ..., n faire j=i*i tant que j≤n faire t[j]=0 j=j+i fait fait
que l'on mettra dans le fichier ~/algo/afftab.c Vous devez utiliser exceed pour passer sous linux. Là vous devez ouvrir une fenêtre shell dans laquelle vous taperez les commandes :#include int main() { const int n=10; int t[10]={4,7,12,3,1,5,7,8,6,10}; int i; for(i=0;i
La commande kate afftab.c ouvre une fenêtre dans laquelle l'éditeur de texte Kate vous permettra de voir et de modifier le fichier afftab.c contenant le programme précédent écrit en C. Le & au bout de cette commande signifie que l'on n'a pas besoin d'attendre la fin de son exécution (c'est-à-dire la fermeture de la fenêtre contenant Kate) pour lancer d'autres commandes.md algo cd algo kate afftab.c & gcc -g -Wall afftab.c ./a.out
cp afftab.c recherche.c kate recherche.c & gcc -g -Wall recherche.c ./a.outLe fichier recherche.c doit ressembler à :
Faire marcher ce programme.#include int main() { const int n=10; int t[10]={4,7,12,3,1,5,7,8,6,10}; int i,x; for(i=0;i
cp recherche.c recherchetrie.cpuis éditer le fichier recherchetrie.c pour qu'il ressemble à :
Faire marcher ce programme.#include int main() { const int n=10; int t[10]={4,7,12,3,1,5,7,8,6,10}; int i,x,j,m; for(i=0;i 0;m--) // tri du tableau t { ... } ... // affichage du tableau trié for(;;) // boucle infinie { printf("Quel nombre recherchez-vous ? "); scanf("%d",&x); if(x<0) break; // On sort de la boucle infinie. // algorithme de recherche dans un tableau trié traduit en C if(i==n) printf("Le nombre %d n'est pas dans le tableau.\n",x); else ... } return 0; }
Quand le programme est au point tapez les commandes#include int main() { int n; printf("Jusqu'où voulez-vous chercher les nombres premiers ? "); scanf("%d",&n); { int t[n+1], i,j; ... printf("Il y a %d nombres premiers inférieurs à %d. Le plus grand d'entre eux est %d.\n",i,n,j); ...
echo 10 | time ./a.out echo 100 | time ./a.out echo 1000 | time ./a.out echo 10000 | time ./a.out echo 100000 | time ./a.out echo 1000000 | time ./a.out echo 10000000 | time ./a.outNoter les temps.
gcc -g -Wall -O2 premiers.cRecommencer en remplaçant if(t[i]==1) par if(1 || t[i]==1). Le temps augmente énormément puisqu'il passe de n*ln(ln(n)) à n*ln(n). Pour n=1000000 le temps passe de 0.05s à 0.25s
Compléter le fichier proctab.c#include"proctab.c" int main() { int n=10,t[n]; printf("Tapez %d nombres\n",n); liretab(t,n); afftab(t,n); tritab(t,n); retourne(t,n); afftab(t,n); return 0; }
de telle sorte qu'une exécution de pp1 ressemble par exemple à#include void afftab(... void liretab(... void tritab(... void retourne(...
La procédure liretab(t,n) lit n nombres dans le fichier d'entrée (a priori le clavier) et les range dans t[0], t[1], ... t[n-1]. Elle n'écrit rien sur le fichier de sortie. Autrement dit elle ne contient que des scanf( ) et pas de printf( ).cc -g -Wall pp1.c ./a.out Tapez 10 nombres 23 12 4 7 2 8 3 10 15 1 23 12 4 7 2 8 3 10 15 1 23 15 12 10 8 7 4 3 2 1
près cela on peut exécuterecho 23 12 4 7 2 8 3 10 15 1 > données
Pour la mise au point du programme, s'il donne un résultat faux, on pourra évidemment rajouter un appel à afftab entre le tri et le retournement du tableau, pour savoir laquelle de ces deux procédures est fausse../a.out < données 23 12 4 7 2 8 3 10 15 1 23 15 12 10 8 7 4 3 2 1
cp pp1.c pp2.cet modifier pp2.c pour qu'il contienne :
#include"proctab.c" int main() { int n,*t; t=liretabn(&n); afftab(t,n); tritab(t,n); retourne(t,n); afftab(t,n); free(t); return 0; }Dans le fichier proctab.c, il faut rajouter la fonction
int *liretabn(int *adn) ...qui doit :
La procédure fusion(n,p,t,u,v) suppose que le tableau t contient n nombres triés dans l'ordre croissant et que le tableau u contient p nombres triés dans l'ordre croissant. Elle doit intercaler ses deux suites de nombres, pour obtenir une suite croissante de n+p nombres qu'elle range dans le tableau v. Elle utilise l'algorithme suivant :void copietab(int n, int t[n], int u[n]) ... // copie t[0], t[1], ... t[n-1] dans u[0], u[1], ... u[n-1] void fusion(int n, int p, int t[n], int u[p], int v[n+p]) ... void trifusion(int t[], int n) { if(n>1) { int m=n/2, p=n-m, *u=t+m; trifusion(t,m); trifusion(u,p); { int v[n]; fusion(m,p,t,u,v); copietab(n,v,t); } } }
tant que les deux suites t et u sont non vides faire On compare le premier élément de t avec le premier élément de u. On prend le plus petit des deux, on l'enlève de la suite à laquelle il appartient (t ou u) et on le rajoute au bout de v. fait Si une des deux suites t ou u est non vide, on la rajoute au bout de v.La procédure trifusion(t,n) trie les n éléments du tableau t. Pour cela on considère que tableau t de taille n=p+m, est constitué d'une première partie, t, de taille m, suivie d'une deuxième partie de taille p. On trie chacune de ces deux parties par un appel récursif. Puis on fusionne ses deux parties triées dans un nouveau tableau v de taille n. On recopie v dans t et on libère la place utilisée par le tableau v. Tout cela n'est utile que si le tableau t contient plusieurs éléments. S'il n'en contient qu'un, il est déjà trié, il n'y a rien à faire.
déplacer les 3 plus petites rondelles de la tige A à la tige C | déplacer les 2 plus petites rondelles de la tige A à la tige B | déplacer la plus petite rondelle de la tige A à la tige C | déplacer 0 rondelle de la tige A à la tige B |
R1 va de A à C | |||
déplacer 0 rondelle de la tige B à la tige C | |||
R2 va de A à B | |||
déplacer la plus petite rondelle de la tige C à la tige B | déplacer 0 rondelle de la tige C à la tige A | ||
R1 va de C à B | |||
déplacer 0 rondelle de la tige A à la tige B | |||
R3 va de A à C | |||
déplacer les 2 plus petites rondelles de la tige B à la tige C | déplacer la plus petite rondelle de la tige B à la tige A | déplacer 0 rondelle de la tige B à la tige C | |
R1 va de B à A | |||
déplacer 0 rondelle de la tige C à la tige A | |||
R2 va de B à C | |||
déplacer la plus petite rondelle de la tige A à la tige C | déplacer 0 rondelle de la tige A à la tige B | ||
R1 va de A à C | |||
déplacer 0 rondelle de la tige B à la tige C |
Le programme précédent doit écriretypedef char *tige; void hanoi(tige depart,tige arrivee,tige autre,int n) { if(n>0) { hanoi( printf( hanoi( } } int main() { hanoi("la tige de gauche","la tige de droite","la tige du milieu",4); return 0; }
On peut mieux voir comment se déroule l'exécution du programme précédent en le rendant plus bavard :La rondelle 1 va de la tige de gauche à la tige du milieu La rondelle 2 va de la tige de gauche à la tige de droite La rondelle 1 va de la tige du milieu à la tige de droite La rondelle 3 va de la tige de gauche à la tige du milieu La rondelle 1 va de la tige de droite à la tige de gauche La rondelle 2 va de la tige de droite à la tige du milieu La rondelle 1 va de la tige de gauche à la tige du milieu La rondelle 4 va de la tige de gauche à la tige de droite La rondelle 1 va de la tige du milieu à la tige de droite La rondelle 2 va de la tige du milieu à la tige de gauche La rondelle 1 va de la tige de droite à la tige de gauche La rondelle 3 va de la tige du milieu à la tige de droite La rondelle 1 va de la tige de gauche à la tige du milieu La rondelle 2 va de la tige de gauche à la tige de droite La rondelle 1 va de la tige du milieu à la tige de droite
Ce programme écrittypedef char *tige; void hanoi(tige depart,tige arrivee,tige autre,int n) { printf("%*s\e[31mdebut de hahoi(%s,%s,%s,%d)\e[30m\n",3*(4-n),"",depart,arrivee,autre,n); if(n>0) { hanoi( printf( hanoi( } printf("%*s\e[31mfin de hahoi(%s,%s,%s,%d)\e[30m\n",3*(4-n),"",depart,arrivee,autre,n); } int main() { hanoi("gauche","droite","milieu",4); return 0; }
debut de hanoi(gauche,droite,milieu,4) debut de hanoi(gauche,milieu,droite,3) debut de hanoi(gauche,droite,milieu,2) debut de hanoi(gauche,milieu,droite,1) debut de hanoi(gauche,droite,milieu,0) fin de hanoi(gauche,droite,milieu,0) 1 va de gauche à milieu debut de hanoi(droite,milieu,gauche,0) fin de hanoi(droite,milieu,gauche,0) fin de hanoi(gauche,milieu,droite,1) 2 va de gauche à droite debut de hanoi(milieu,droite,gauche,1) debut de hanoi(milieu,gauche,droite,0) fin de hanoi(milieu,gauche,droite,0) 1 va de milieu à droite debut de hanoi(gauche,droite,milieu,0) fin de hanoi(gauche,droite,milieu,0) fin de hanoi(milieu,droite,gauche,1) fin de hanoi(gauche,droite,milieu,2) 3 va de gauche à milieu debut de hanoi(droite,milieu,gauche,2) debut de hanoi(droite,gauche,milieu,1) debut de hanoi(droite,milieu,gauche,0) fin de hanoi(droite,milieu,gauche,0) 1 va de droite à gauche debut de hanoi(milieu,gauche,droite,0) fin de hanoi(milieu,gauche,droite,0) fin de hanoi(droite,gauche,milieu,1) 2 va de droite à milieu debut de hanoi(gauche,milieu,droite,1) debut de hanoi(gauche,droite,milieu,0) fin de hanoi(gauche,droite,milieu,0) 1 va de gauche à milieu debut de hanoi(droite,milieu,gauche,0) fin de hanoi(droite,milieu,gauche,0) fin de hanoi(gauche,milieu,droite,1) fin de hanoi(droite,milieu,gauche,2) fin de hanoi(gauche,milieu,droite,3) 4 va de gauche à droite debut de hanoi(milieu,droite,gauche,3) debut de hanoi(milieu,gauche,droite,2) debut de hanoi(milieu,droite,gauche,1) debut de hanoi(milieu,gauche,droite,0) fin de hanoi(milieu,gauche,droite,0) 1 va de milieu à droite debut de hanoi(gauche,droite,milieu,0) fin de hanoi(gauche,droite,milieu,0) fin de hanoi(milieu,droite,gauche,1) 2 va de milieu à gauche debut de hanoi(droite,gauche,milieu,1) debut de hanoi(droite,milieu,gauche,0) fin de hanoi(droite,milieu,gauche,0) 1 va de droite à gauche debut de hanoi(milieu,gauche,droite,0) fin de hanoi(milieu,gauche,droite,0) fin de hanoi(droite,gauche,milieu,1) fin de hanoi(milieu,gauche,droite,2) 3 va de milieu à droite debut de hanoi(gauche,droite,milieu,2) debut de hanoi(gauche,milieu,droite,1) debut de hanoi(gauche,droite,milieu,0) fin de hanoi(gauche,droite,milieu,0) 1 va de gauche à milieu debut de hanoi(droite,milieu,gauche,0) fin de hanoi(droite,milieu,gauche,0) fin de hanoi(gauche,milieu,droite,1) 2 va de gauche à droite debut de hanoi(milieu,droite,gauche,1) debut de hanoi(milieu,gauche,droite,0) fin de hanoi(milieu,gauche,droite,0) 1 va de milieu à droite debut de hanoi(gauche,droite,milieu,0) fin de hanoi(gauche,droite,milieu,0) fin de hanoi(milieu,droite,gauche,1) fin de hanoi(gauche,droite,milieu,2) fin de hanoi(milieu,droite,gauche,3) fin de hanoi(gauche,droite,milieu,4)
Avant le programme principal, on doit mettre des fonctions qui :typedef int nombre; #define format "%d" nombre somme(int n,nombre t[n]) ... int main() { int n=5; nombre t[]={4,2,7,3,6}; ... printf("La somme des %d éléments du tableau est "format"\n",n,somme(n,t)); printf("Le plus grand est "format"\n",maxi(n,t)); ... a=4; b=6; echange(&a,&b); printf("a="format" b="format"\n",a,b); tri2 (&a,&b); printf("a="format" b="format"\n",a,b); ...
Le programme principal est uniquement là pour tester les fonctions. Il doit être le plus simple possible.typedef int double; #define format "%f"
cc -Wall -g -O2 -c trirapide.c cc -Wall -g -O2 -c trin2.c cc -Wall -g -O2 -c trifusionit.c cc -Wall -g -O2 -c trifusionrec.c cc -Wall -g -O2 -c trishell.c cc -Wall -g -O2 -c rechtrien.c cc -Wall -g -O2 -c rechdichoit.c cc -Wall -g -O2 -c rechdichorec.c cc -Wall -g -O2 -c testri.c cc testri.o trirapide.o rechdichoit.o echo 100000 | time ./a.outtesttri.c contiendra :
Les tris en n ln(n) comme le tri rapide ou le tri fusion doivent mettre moins d'une seconde pour trier un tableau de 100000 éléments. Le tri en n2 doit mettre environ une minute.#include #include void tri(int n,double t[n]); int recherche(int n,double t[n],double x); void aff(int n,double t[n]) ... double somme(int n,double t[n]) ... int main() { int n; printf("Combien ..."); scanf("%d",&n); { double t[n], s1, s2; int i, x=0; for(i=0;i =t[i]) printf("Ce n'est pas trié\n"),exit(1); if(s1!=s2) printf("La somme a changé\n"),exit(1); // test de recherche i=n/3; if(recherche(n,t,t[i])!=i) printf("recherche n'a pas trouvé %f.\n",t[i]),exit(1); if(recherche(n,t,99.9)!=n) printf("recherche a trouvé 99.9.\n"),exit(1); printf("C'est bon.\n"); } return 0; }
trishell.c contiendra :/* pour l=1, 2, 4, 8, etc tant que i
k&-k est la plus grande puissance de 2 qui divise k. Donc k/(k&-k) est le nombre obtenu en divisant k par 2 tant que l'on peut, jusqu'à ce que l'on obtienne un nombre impair. Pour savoir si ce nombre est une puissance de 3 il suffit de vérifier s'il divise 319. On pourrait aussi appliquer l'algorithme suivant :/* pour tous les entiers k inférieurs à n produit d'une puissance de 2 par une puissance de 3 pris dans l'ordre décroissant faire pour tout les entiers i de 0 à n-k-1 faire si t[i]>t[i+k] alors echanger t[i] et t[i+k] finsi fait fait */ void tri(int n,double t[n]) { int k,i; double x; for(k=n;--k;) if(1162261467%(k/(k&-k))==0) for(i=0;i+k
pour k=n-1,n-2, ... ,3,2,1 faire i:=k tant que i est pair faire i/=2 fait tant que i est divisible par 3 faire i/=3 fait si i==1 alors pour tous les entiers i de 0 à n-k-1 faire si t[i]>t[i+k] alors echanger t[i] et t[i+k] finsi fait finsi faittrirapide.c contiendra :
/* si il y a plusieurs éléments dans le tableau alors choisir un élément x du tableau (par exemple le premier) on fait pointer deb sur le premier élément du tableau on fait pointer fin sur le dernier élément du tableau tant que deb =x on fait reculer fin jusqu'au premier élément <=x si deb 1) { int deb=0,fin=n-1; double x=t[0], y; for(;;) { while(t[deb] x) fin--; if(fin<=deb) break; y=t[fin], t[fin]=t[deb], t[deb]=y; fin--, deb++; } // 0..deb-1 fin=deb fin+1..n-1 // 0..deb-1=fin deb=fin+1..n-1 tri(deb,t); tri(n-fin-1,t+fin+1); } }
corrigé#include #include typedef struct chainon chainon, *liste; struct chainon{int val; liste suite;}; void aff(liste l)// affiche sur l'écran tous les éléments de la liste, itérativement {//... } liste nouv(int val, liste suite)// rend un pointeur sur un nouveau noeud (alloué par malloc) contenant val et suite [... // par exemple p=nouv(2,p); ajoute 2 en tête de la liste p. } liste copie(liste l) {return l ? nouv(l->val,copie(l->suite)) : 0;} int somre(liste l) {return l ? l->val+somre(l->suite) : 0;} int somit(liste l) // même résultat que somre mais itérativement (sans appel récursif) {//... } void add1(liste l) {for(;l;l=l->suite) l->val++;} liste eipoc(liste l)// fait une copie de la liste dans l'ordre inverse, itérativement {//... } liste retourne(liste l)// retourne la liste en gardant les mêmes chaînons, itérativement {//... } void retour(liste *l) {*l=retourne(*l);} void affrec(liste l) // affiche sur l'écran tous les éléments de la liste, récursivement {/*...*/} void ffa (liste l) // affiche la liste à l'envers {/*...*/} typedef struct {liste tete,fin;} lliste; // tete pointe sur le premier chainon et fin sur le dernier. // La liste est vide ssi tete==0, et dans ce cas fin n'est pas défini. void ajoutetete(lliste *a,int x) { //.. } void ajoutefin(lliste *a,int x) { //.. } int enlevetete(lliste *a,int *x) { //.. } liste fusionrec(liste a,liste b) // fusionne les liste a et b, qui sont déjà triées en une liste triée, en réutilisant les mêmes chainons { //.. } liste fusionit(liste a,liste b) { //.. } liste trifusion(liste l) { liste p=0,r=0; while(l) { liste q=l; l=q->suite, // on enleve un chainon q en tete de l q->suite=p, p=r, r=q; // on le met en tete de p, puis on echange p et r } return !p ? r : fusion(trifusion(p),trifusion(r)); } int main(){ liste l=nouv(3,nouv(7,nouv(5,nouv(1,0)))), k=copie(l), m=l; affrec(l), ffa(l), printf("\n"); aff(l), aff(k), aff(m); printf("%d=%d\n",somre(l),somit(l)); add1(l); aff(l), aff(k), aff(m=eipoc(m)); lliste ll={0,0}; int x,y; for(x=0;x<10;x++) (x&1 ? ajoutetete : ajoutefin)(&ll,x), aff(ll.tete); while(enlevetete(&ll,&x) && enlevetete(&ll,&y)) ajoutefin(&ll,x+y-3), aff(ll.tete); for(x=1;x;x=(x*2+1)%11) l=nouv(x,l); aff(l); retour(&l); aff(l); aff(l=trifusion(l)); return 0; }
Si le graphe est orienté, on peut construire pour chaque sommet la liste de ses successeurs et la liste de ses prédécesseurs.#include #include typedef struct arete{int origine,extremite;} arete; typedef struct chainon *listesom; struct chainon{int s; listesom suite;}; listesom nouv(int s,listesom suite) { listesom a=malloc(sizeof(*a)); a->s=s; a->suite=suite; return a; } void cherchevoisins(int n,int a, arete ar[a], listesom voisins[n])// construit voisins { int i; for(i=0;i suite) printf(" %d",p->s); printf("\n"); } } return 0; }
Pour chercher tous les sommets que l'on peut atteindre à partir du sommet s0 on peut appliquer l'algorithme suivant#include #include typedef struct arete{int origine,extremite;} arete; typedef struct chainon *listesom; struct chainon{int s; listesom suite;}; listesom nouv(int s,listesom suite) { listesom a=malloc(sizeof(*a)); a->s=s; a->suite=suite; return a; } void succpred(int n,int a, arete ar[a], listesom succ[n], listesom pred[n])// construit voisins { int i; for(i=0;i suite) printf(" %d",a->s);} int main() { int n=4, a=5; arete ar[]={{0,1},{1,2},{2,3},{3,0},{2,0}}; listesom succ[n],pred[n]; succpred(n,a,ar,succ,pred); { int i; for(i=0;i
on marque s0 l={s0} tant que l n'est pas vide on enlève un élément x de l pour chacun des successeurs y de x faire si y n'est pas marqué alors on marque y on ajoute y à l finsi fait faitl est la liste des sommets que l'on a marqués, mais dont on n'a pas encore marqué les successeurs.
#include #include typedef struct arete{int origine,extremite;} arete; typedef struct chainon *listesom; struct chainon{int s; listesom suite;}; listesom nouv(int s,listesom suite) { listesom a=malloc(sizeof(*a)); a->s=s; a->suite=suite; return a; } void succpred(int n,int a, arete ar[a], listesom succ[n], listesom pred[n])// construit voisins { int i; for(i=0;i suite) printf(" %d",a->s);} void parcours(int c, listesom succ[], int marque[]) { listesom p; marque[c]=1; for(p=succ[c];p;p=p->suite) if(!marque[p->s]) parcours(p->s,succ,marque); } int main() { int n=4, a=5; arete ar[]={{0,1},{1,2},{2,3},{3,0},{2,0}}; listesom succ[n],pred[n]; succpred(n,a,ar,succ,pred); { int i; for(i=0;i
1) Qu'écrit ce programme quand on l'exécute ?#include #include int f1(int n,int p) { return p<0 ? 0 : 2*p>n ? f1(n,n-p) : p ? f1(n-1,p-1)*n/p : 1; } int f2(int n,int p) { return p<0 || p>n ? 0 : n ? f2(n-1,p)+f2(n-1,p-1) : 1; } int f3(int n,int p) { if(n-p x=x; a->suite=suite; return a; } void ajt(lliste *a,int x) { a->tete=nouv(x,a->tete); if(!a->tete->suite) a->queue=a->tete; } void ajq(lliste *a,int x) { if(a->tete) a->queue=a->queue->suite=nouv(x,a->queue); else a->queue=a->tete =nouv(x,0); } int pop(lliste *a) { liste t=a->tete; int x=t->x; a->tete=t->suite; free(t); return x; } int main() { lliste a={0,0}; int t[]={ 4 , 8 , 3 , 2 , 7 },x,y,i; int n=14,p=10; printf("%d %d %d\n",f1(n,p),f2(n,p),f3(n,p)); for(i=0;i<5;i++) ajq(&a,t[i]); for(i=0;i<4;i++) x=pop(&a), y=pop(&a), printf("%d+%d=%d\n",x,y,x+y), ajq(&a,x+y); return 0; }
procédure parcours_en_profondeur_ou_largeur_d'abord(s:sommet) pour chacun des sommets i faire on note que i n'a pas encore été visité O(n) fait l=(s) // liste des sommets déjà visités, dont on n'a pas encore visité les successeurs on note que s a été visité tant que l n'est pas vide faire Soit i le dernier ou le premier élément de l. Si i a un successeur j qui n'a pas encore été visité alors O(a) on ajoute j à la fin de l O(n) on note que j a été visité O(n) sinon en enlève i de l finsi fait fin procédureAutrement dit, on part d'une liste qui au début ne contient que le sommet de départ. Puis tant que la liste n'est pas vide si le prochain élément à examiner à encore un successeur qui n'est pas encore rentré dans la liste, alors on ajoute ce successeur à la liste, sinon on enlève ce prochain de la liste.
Dans le programme pécédent on peut modifier la procédure de parcours en largeur d'abord, pour lui faire calculer la distance du sommet de départ à chacun des autres sommets et construire un arbre formé de chemins de longueur minimale allant du sommet de départ à chacun des autres sommets.#include #include typedef struct arete{int origine,extremite;} arete; typedef struct chainon *listesom; struct chainon{int s; listesom suite;}; listesom nouv(int s,listesom suite) { listesom a=malloc(sizeof(*a)); a->s=s; a->suite=suite; return a; } void succpred(int n,int a, arete ar[a], listesom succ[n], listesom pred[n])// construit voisins { int i; for(i=0;i suite) printf(" %d",a->s);} void parcours(int c, listesom succ[], int marque[]) // récursif en profondeur d'abord { listesom p; marque[c]=1; for(p=succ[c];p;p=p->suite) if(!marque[p->s]) parcours(p->s,succ,marque); } void parcours_ite_prof(int s, listesom succ[], int n, int marque[n]) // itératif en profondeur d'abord { listesom p; int l[n], nl,i,j; marque[s]=1; // on note que s a été visité l[0]=s, nl=1; // l=(s) while(nl) // tant l n'est pas vide { i=l[nl-1]; // on met dans i le dernier élément de l for(p=succ[i];p && marque[p->s];p=p->suite) ; // On cherche le prochain successeur de i non visité. succ[i]=p; if(p) marque[l[nl++]=p->s]=1; // on note que ce successeur a été visité et on l'ajoute la fin de la liste l else nl--; // on enlève i de la liste l } // fait } void parcours_ite_larg(int s, listesom succ[], int n, int marque[n]) // itératif en largeur d'abord { listesom p; int l[n], dl,fl,i,j; marque[s]=1; // on note que s a été visité l[0]=s, dl=0, fl=1;// l=(s) while(dl suite) // pour chaque successeur j (=p->s) de i faire if(!marque[j=p->s]) // si j n'a pas encore été visité alors { marque[j]=1; // on note que j a été visité l[fl++]=j; // on ajoute j à la fin de la liste l } // finsi fait } // fait } int main() { int n=4, a=5; arete ar[]={{0,1},{1,2},{2,3},{3,0},{2,0}}; listesom succ[n],pred[n],suc[n]; succpred(n,a,ar,succ,pred); { int i; for(i=0;i
void parcours_ite_larg(int s, listesom succ[], int n, int marque[n],int pere[n], int dist[n]) // récursif en largeur d'abord { listesom p; int l[n], dl,fl,i,j; marque[s]=1; // on note que s a été visité l[0]=s, dl=0, fl=1;// l=(s) pere[s]=-1, dist[s]=0;// s n'a pas de père puisque c'est la racine de l'arbre, la distance de s à s et 0. while(dl suite) // pour chaque successeur j (=p->s) de i faire if(!marque[j=p->s]) // si j n'a pas encore été visité alors { marque[j]=1; // on note que j a été visité l[fl++]=j; // on ajoute j à la fin de la liste l dist[j]=dist[i]+1, pere[j]=i; } // finsi fait } // fait } int main() { int n=4, a=5; arete ar[]={{0,1},{1,2},{2,3},{3,0},{2,0}}; listesom succ[n],pred[n]; succpred(n,a,ar,succ,pred); { int i; for(i=0;i =0;k=pere[k]) printf(" %d",k); printf("\n"); } return 0; }