Arbres n-aires

Transcription

Arbres n-aires
Arbres n-aires
14/04/06
Bac2 - JMD - Arbrnair
NOEUD
pcontenu
MAILLON
LISTE
plstsucs
psuiv
psuiv
pprec
pprec
pcontenu
pcontenu
pdebut
pfin
pcontenu
pcontenu
plstsucs
plstsucs
psuiv
pdebut
pdebut
pprec
pfin
pfin
pcontenu
Arbre n-aire
Bac2 - JMD - ArbrNair
1
Bac2 - JMD - ArbrNair
2
Fonctions du module
ArbrNair
/*-----------------------------------------------------------------------------------------------------------------Crée et initialise un noeud de contenu pointé par <q>. Retourne l'adresse du noeud
créé. Retourne NULL en cas d'erreur.
NB Le noeud mémorise l'adresse du contenu sans plus.
------------------------------------------------------------------------------------------------------------------*/
NOEUD * ANCreer_Noeud(void * q);
/*----------------------------------------------------------------------------------------------------------------Ajoute un sous-arbre n-aire <an> à un noeud <a>. Retourne 1 en cas de succès et 0
dans le cas contraire (problème d'allocation par exemple).
------------------------------------------------------------------------------------------------------------------*/
int ANAjoutSArbre(ARBRNAIR an, NOEUD * a);
/*-----------------------------------------------------------------------------------------------------------------Construit un arbre n-aire d'adresse <a> à l'aide de la fonction <ConstrArbrNair> fournie
par l'appelant. Retourne 0 en cas d'erreur et 1 dans le cas contraire.Une valeur nulle
dans <*a> indique un arbre vide.
------------------------------------------------------------------------------------------------------------------*/
int ANConstruire(ARBRNAIR *a, int ConstrArbrNair(ARBRNAIR *));
/*----------------------------------------------------------------------------------------------------------------Affiche l'arbre n-aire donné par l'adresse de son noeud racine <a> sous
forme d'une expression parenthésée conforme à la grammaire suivante :
<arbrnair>
::=
<arbrnairs>
::=
<etiquette>
<lettresouchiffres>
::=
::=
( <etiquette> <arbrnairs> )
| empty
<arbrnair> <arbrnairs>
| empty
<lettre> <lettresouchiffres>
<lettre> <lettresouchiffres>
| <chiffre> <lettresouchiffres>
| empty
NB Une étiquette de n ud <etiquette> n’est jamais vide!
La fonction <AffichContenu> fournie par l'appelant permet d'afficher le contenu d'un
noeud.
------------------------------------------------------------------------------------------------------------------*/
void ANAfficher(ARBRNAIR a, void AffichContenu(void *));
14/04/06
Bac2 - JMD - Arbrnair
3
Fonctions du module
ArbrNair (suite)
/*---------------------------------------------------------------------------------------------------------------Retourne la profondeur d'un arbre n-aire donné par l'adresse de son noeud racine
<a>. La profondeur d'un arbre est le nombre de noeuds sur le plus long chemin de la
racine à une feuille (noeud sans successeur). La profondeur de l'arbre vide (pointeur
sur racine null, sans noeud) est 0.
Définition récursive : la profondeur d'un arbre n-aire est la profondeur du plus profond
de ses s-arbres augmentée de 1.
----------------------------------------------------------------------------------------------------------------*/
int ANProfondeur(ARBRNAIR a);
/*--------------------------------------------------------------------------------------------------------------Détruit un arbre n-aire donné par l'adresse d'un emplacement <*a> qui contient
l'adresse de son noeud racine. La destruction d'un arbre n-aire consiste en la
libération de tous les emplacements de mémoire dynamique (obtenus par malloc) qu'il
occupe. Après la destruction, la fonction range la valeur NULL dans l'emplacement
<*a> pour signifier que l'arbre résultant est vide.
Définition récursive : Détruire un arbre n-aire, c'est détruire ses sous-arbres et libérer
la place occupée par son noeud racine.
La fonction <LibererContenu> fournie par l'appelant permet de libérer lecontenu d'un
noeud.
----------------------------------------------------------------------------------------------------------------*/
void ANDetruire(ARBRNAIR * a, void LibererContenu(void *));
14/04/06
Bac2 - JMD - Arbrnair
4
Fonctions du module Liste
utilisées dans le module Arbrnair
/* -----------------------------------------------------------------------------------------------------------------Crée une liste vide (pas de maillon) et en retourne l'adresse.
------------------------------------------------------------------------------------------------------------------ */
LISTE * ListCreer(void);
/* -----------------------------------------------------------------------------------------------------------------Ajoute un maillon avant le premier maillon actuel dans la liste <plst>, lui attache le
contenu d'adresse <pcont> et retourne l'adresse du maillon ajouté.
------------------------------------------------------------------------------------------------------------------ */
MAILLON * ListAjouterDeb(LISTE *plst, void * pcont);
/* -----------------------------------------------------------------------------------------------------------------Retourne l'adresse du premier maillon de la liste <plst>.
------------------------------------------------------------------------------------------------------------------ */
MAILLON * ListDebut(LISTE *plst);
/* -----------------------------------------------------------------------------------------------------------------Retourne l'adresse du maillon qui suit le maillon d'adresse <pcourant> dans la liste
<plst>.
------------------------------------------------------------------------------------------------------------------ */
MAILLON * ListSuivant( MAILLON * pcourant);
/* -----------------------------------------------------------------------------------------------------------------Retourne l'adresse du contenu du maillon d'adresse <pcourant>.
------------------------------------------------------------------------------------------------------------------ */
void * ListDonContenu(MAILLON * pcourant);
/* -----------------------------------------------------------------------------------------------------------------Met le contenu du maillon d'adresse <pcourant> à la valeur <pcontenu>.
------------------------------------------------------------------------------------------------------------------ */
void ListMetContenu(MAILLON * pcourant, void * pcont);
/* -----------------------------------------------------------------------------------------------------------------Détruit la liste <plst> y compris ses contenus et retourne NULL.
------------------------------------------------------------------------------------------------------------------ */
LISTE * ListDetruire(LISTE * plst);
14/04/06
Bac2 - JMD - Arbrnair
5
Visite en profondeur
d’abord d’un arbre naire
void VisiterProfondAux (ARBRNAIR arbrnair) {
MAILLON * p;
ARBRNAIR a;
printf("%s ",arbrnair->pcontenu);
p=ListDebut(arbrnair->plstsucs);
while(p) {
a=ListDonContenu(p);
// Obtenir fils
VisiterProfondAux(a);
// Descente
p=ListSuivant(p);
// Essai fils suivant
}
return;
// Plus ou pas de fils :
// retour au parent ou
// « backtracking »
}
void VisiterProfond(ARBRNAIR arbrnair) {
if (arbrnair) VisiterProfondAux(arbrnair);
printf("\n");
}
14/04/06
Bac2 - JMD - Arbrnair
6
Visiter pour trouver et traiter
un noeud « particulier » (1)
void CherchNoeudDansAux(ARBRNAIR arbrnair,
int Propriete(NOEUD *),
void Traitement(NOEUD *))
{
MAILLON * p;
ARBRNAIR a;
if (Propriete(arbrnair)) {
Traitement(arbrnair);
return ;
// Le noeud "racine" a la propriété requise
// Traiter le noeud
// retour en arrière au parent ou
// "backtracking"
} else {
p=ListDebut(arbrnair->plstsucs);
while(p) {
a=ListDonContenu(p);// Obtenir fils
// Descente
CherchNoeudDansAux(a,Propriete,Traitement);
p=ListSuivant(p);
// Essai fils suivant
}
// Pas ou plus de fils(tous "visités") :
return;
// retour en arrière au parent
}
}
14/04/06
Bac2 - JMD - Arbrnair
7
Visiter pour trouver et traiter
un noeud « particulier » (2)
void CherchNoeudDans( ARBRNAIR arbrnair,
int Propriete(NOEUD *),
void Traitement(NOEUD *))
{
if (arbrnair)
CherchNoeudDansAux(arbrnair,Propriete,Traitement);
printf("\n");
}
int Tester_Propriete(NOEUD * pn) {
return !strcmp(pn->pcontenu,"c");
}
void Traiter_Noeud(NOEUD * pn) {
printf("Encore un noeud de contenu %s\n",pn->pcontenu);
}
14/04/06
Bac2 - JMD - Arbrnair
8
Programme principal
test arbre n-aire
#include <stdio.h>
#include <crtdbg.h>
#include "ArbrNair.h«
// autres includes
// Construit un arbre n-aire d'adresse <a>.
int Construire(ARBRNAIR * a) { /*etc.*/ }
// Affichage d'un contenu
void AffEtiquet(char * etq) { /*etc.*/ }
// Libération d'un contenu
void LiberCont(void * pcont) { /*etc.*/ }
int main() {
ARBRNAIR arbrnair;
arbrnair=NULL;
if (ANConstruire(&arbrnair,Construire)) {
printf("ok\n");
ANAfficher(arbrnair, AffEtiquet);
VisiterProfond(arbrnair);
printf("Profondeur : %d\n",ANProfondeur(arbrnair));
Cherch_Noeud_Dans(arbrnair,
Tester_Propriete,Traiter_Noeud);
}
ANDetruire(&arbrnair,LiberCont);
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtDumpMemoryLeaks( );
return 0;
}
14/04/06
Bac2 - JMD - Arbrnair
9
Visiter un arbre implicite
pour trouver une solution
•
L’arbre n’est jamais totalement mémorisé et est
alors qualifié d’« implicite » :
– il est visité en profondeur d’abord, racine en
premier puis sous-arbres de gauche à droite;
– les successeurs de chaque n ud visité sont
mémorisés jusqu’à ce que tous les descendants de
ce n ud aient été visités aussi;
– L’ensemble des n uds en cours de visite
constituent un chemin dans l’arbre qui lui aussi est
mémorisé (solution partielle à confirmer ou infirmer)
14/04/06
Bac2 - JMD - Arbrnair
10
Visiter un arbre implicite
pour trouver une solution
• Le chemin est mémorisé sous la forme
d’une pile (des contenus) des n uds
constitutifs, le (contenu du) n ud courant
étant au sommet de la pile (FIFO).
• Les (contenus des) candidats successeurs
ou fils du n ud courant sont mémorisés
dans une file (LIFO) pour être essayés
successivement.
14/04/06
Bac2 - JMD - Arbrnair
11
Rappels
Pile (LIFO)
/* --------------------------------------------------------------------------Créer une pile vide (pas d’élément) et retourner son adresse.
--------------------------------------------------------------------------- */
PILELIFO * PilCreer(void);
/* --------------------------------------------------------------------------Retourner "vrai" si la pile <*ppil> est vide. Sinon retourner "faux".
--------------------------------------------------------------------------- */
int PilVide(PILELIFO *ppil);
/* --------------------------------------------------------------------------Empiler un contenu d’adresse <pcont> sur la pile <ppil>.
--------------------------------------------------------------------------- */
void PilPush(PILELIFO *ppil, void * pcont);
/* --------------------------------------------------------------------------Désempiler le contenu au sommet de la pile <ppil> et retourner l'adresse
du contenu.
--------------------------------------------------------------------------- */
void * PilPop(PILELIFO *ppil) ;
/* --------------------------------------------------------------------------Destruire la pile <ppil> y compris les contenus et retourner NULL.
--------------------------------------------------------------------------- */
PILELIFO * PilDetruire(PILELIFO * ppil);
14/04/06
Bac2 - JMD - Arbrnair
12
Rappels
File (FIFO)
/* --------------------------------------------------------------------------Créer une file vide (pas d’élément) et retourner son adresse.
--------------------------------------------------------------------------- */
FILEFIFO * FilCreer(void);
/* --------------------------------------------------------------------------Retourner "vrai" si la file <*pfil> est vide. Sinon retourner "faux".
--------------------------------------------------------------------------- */
int FilVide(FILEFIFO *pfil);
/* --------------------------------------------------------------------------Ajouter un contenu d’adresse <pcont> à la fin de la file <pfil>.
--------------------------------------------------------------------------- */
void FilAjouter(FILEFIFO *pfil, void * pcont);
/* --------------------------------------------------------------------------Retirer le contenu à la fin de la file <pfil> et retourner de l'adresse
du contenu.
--------------------------------------------------------------------------- */
void * FilRetirer(FILEFIFO *pfil) ;
/* --------------------------------------------------------------------------Destruire la file <pfil> y compris les contenus et retourner NULL.
--------------------------------------------------------------------------- */
FILEFIFO * FilDetruire(FILEFIFO * pfil);
14/04/06
Bac2 - JMD - Arbrnair
13
void Cherch_Solution( PILELIFO * part_sol,DATA input,
int Est_Solution(PILELIFO *, DATA),
void Traiter_Solution(PILELIFO *, DATA),
void Determiner_Successeurs(PILELIFO *, DATA,FILEFIFO *)) {
FILEFIFO * successeurs;
// File des successeurs du noeud courant
if (Est_Solution(part_sol,input)) {
Traiter_Solution(part_sol,input);
return ;
} else {
successeurs=FilCreer(); // Créer file vide.
// Ajouter les successeurs du dernier noeud de <part_sol>.
Determiner_Successeurs(part_sol,input,successeurs);
while (!FilVide(successeurs)) {
// Ajouter à solution partielle <part_sol>, un successeur de son dernier noeud
PilPush(part_sol, FilRetirer(successeurs));
// Chercher une solution qui intègre (qui commence par) la solution partielle
// augmentée de ce successeur
Cherch_Solution(part_sol,input, Est_Solution,
Traiter_Solution,Determiner_Successeurs);
// BackTrack ou remontée : la recherche des solutions qui intègrent la solution
// partielle augmentée est terminée. Retirer le successeur essayé.
free(PilPop(part_sol));
}
// Tous les successeurs du dernier noeud de la solution partielle <part_sol> essayés.
// Retour de <part_sol> à sa valeur d'entrée.
successeurs=FilDetruire(successeurs);
return;
}
}
14/04/06
Bac2 - JMD - Arbrnair
14
Parties d’ensemble
Fonctions complémentaires
// entree_suppl différent de NULL
bool Est_Sol (PILELIFO * solution,
DATA entree_suppl)
int n; MAILLON *pmaillon;
pmaillon=ListDebut((LISTE *)solution); n=0;
while(pmaillon) {
n++;
pmaillon=ListSuivant(pmaillon));
}
return n==(*((int*)entree_suppl));
}
{
void Traiter_Sol (PILELIFO * solution,
DATA entree_suppl)
{
int n; MAILLON *pmaillon;
printf("{");
pmaillon=ListFin((LISTE *)solution); n=0;
while(pmaillon) {
n++;
if(*((int *)ListDonContenu(pmaillon)))printf(" %d",n);
pmaillon=ListPrecedent(pmaillon));
}
printf("}\n");
}
14/04/06
Bac2 - JMD - Arbrnair
15
Parties d’ensemble
Fonctions complémentaires
void Determiner_Succes (PILELIFO * part_sol,
DATA entree_suppl,FILEFIFO * successeurs)
{
int *pval1, *pval2;
pval1=malloc(sizeof(int));
assert(pval1);
(*pval1)=1;
FilAjouter(successeurs,pval1);
pval2=malloc(sizeof(int));
assert(pval2);
(*pval2)=0;
FilAjouter(successeurs,pval2);
}
14/04/06
Bac2 - JMD - Arbrnair
16
Parties de l’ensemble
des n premiers entiers positifs
// #includes
int main() {
PILELIFO * plifo;
int info=3;
plifo=PilCreer();
// Parties de l’ensemble {1,2,3}
// Solution partielle vide au départ
Cherch_Solution(plifo,&info,Est_Sol,Traiter_Sol,
Determiner_Succes);
plifo=PilDetruire(plifo);
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtDumpMemoryLeaks( );
return 1;
}
14/04/06
Bac2 - JMD - Arbrnair
17

Documents pareils