Contents
- arbre.h
- arbre.c
arbre.h 1/2
[top][prev][next]
struct _node {
struct _node **fils; /*data structure */
int degre; /* Arite du noeud, managed in data structure */
char *name; /* Etiquette */
// some printing stuff
int height; /* hauteur du noeud (feuille==0) */
int hpos; /* indentation pour impression horizontale */
// feuilles = pas fixe, autres noeud = barycentre des fils
};
typedef struct _node node;
typedef node *arbre;
/* data structure */
extern arbre new_arbre(const char *name, ...);
// utilisation varargs : new_arbre("Non", f1 ,f2 ,..., NULL)
// avec fi de type arbre
extern void free_arbre(arbre tree);
/* macros pratiques */
#define N(args...) new_arbre(args, NULL) // arg0 = const char *, argi = arbre //
#define F(name) new_arbre((name), NULL) // Feuille == N(name)
/* Impressions Ligne (avec parentheses) */
extern void print_arbre_pre(arbre tree); // impr. ligne : prefixe
extern void print_arbre_post(arbre tree); // impr. ligne :postixe
extern void print_arbre_inf(arbre tree); // impr. lign : infixe
extern void print_arbre_leaf(arbre tree); // impr. ligne : leaf-only
/* Impresions Verticales */
extern void print_arbre(arbre tree); // impression verticale avec branche
extern void print_arbre_bis(arbre tree); // version simple sans branche
/* Impressions Horizontales */
#define MAX_LIGNE 255 /* largeur max ligne, troncage des depassements */
#define H_PRINT_TAB 7 /* espacement entre noeud en nb de char */
#define H_PRINT_INDENT 1 /* indentation initial en nb de char */
extern void print_arbre_prof(arbre tree); /* impr. par profondeur avec de belles branches */
extern void print_arbre_height(arbre tree); /* impr. par hauteur avec les feuilles en haut */
/* */
extern void Recurse(arbre tree, void (*PreFonct) (arbre) , void (*PostFonct) (arbre));
extern void Recurse_prof(arbre tree, void (*PreFonct) (arbre), int prof);
extern void Recurse_height(arbre tree, void (*PreFonct) (arbre ), int height);
arbre.c 2/2
[top][prev][next]
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "arbre.h"
#define MAX(a,b) (((a)>(b))?(a):(b))
arbre new_arbre(const char *name, ...) { //versions new_tree("Non", f1 ,f2 ,f3, NULL)
arbre temp;
int i;
int n_args;
va_list argp;
temp = (arbre)malloc(sizeof(node));
temp->name=strdup(name);
temp->degre=0;
temp->hpos=0;
temp->height=0;
temp->fils=NULL;
va_start(argp,name); n_args=0;
while(va_arg(argp, arbre) != NULL) n_args++;
va_end(argp);
temp->degre=n_args;
if (temp->degre !=0) {
temp->fils=(arbre *) calloc(temp->degre, sizeof(arbre));
va_start(argp,name);
for(i=0; i<n_args; i++) {
temp->fils[i]=va_arg(argp, arbre) ;
temp->height=MAX(temp->fils[i]->height+1,temp->height);
}
va_end(argp);
}
return(temp);
}
// Traverse with Function as parameter
void Recurse(arbre tree, void (*PreFonct) (arbre) , void (*PostFonct) (arbre)) {
int i;
if (tree==NULL) return;
if (PreFonct!=NULL) PreFonct(tree);
for(i=0; i<tree->degre; i++)
Recurse(tree->fils[i],PreFonct,PostFonct);
if (PostFonct!=NULL) PostFonct(tree);
}
// Free
void free_arbre(arbre tree) {
void free_node(arbre tree){
free(tree->name);
free(tree->fils);
free(tree);
}
Recurse(tree,NULL, free_node);
}
/* impressions "classiques" */
void print_arbre_bis(arbre tree) { /*impression verticale */
void print_tree(arbre tree, int level) {
int i;
if (tree==NULL) return;
for(i=0;i<level;i++) printf(" ");
printf("%s (%d)\n", tree->name, tree->degre);
for(i=0; i<tree->degre; i++)
print_tree(tree->fils[i],level+1);
}
print_tree(tree,1);
}
void print_arbre(arbre tree) { /*avec les branches */
char indent[256];
void print_tree1(arbre tree, int level, int last) {
int i;
if (tree==NULL) return;
indent[3*level]='\0';
printf("%s|\n", indent);
printf("%s", indent);
if (last) {printf("\\--"); sprintf(indent,"%s ",indent);}
else {printf("|--"); sprintf(indent,"%s| ",indent);}
printf("%s (%d)\n", tree->name, tree->degre);
for(i=0; i<tree->degre; i++)
print_tree1(tree->fils[i],level+1,(i==(tree->degre-1)));
}
print_tree1(tree,0,1);
}
void print_arbre_pre(arbre tree) { /* prefixe */
void pre(arbre tree){
if (tree->degre !=0) printf(" (");
printf(" %s", tree->name);
}
void post(arbre tree){
if (tree->degre !=0) printf(" )");
}
Recurse(tree,pre,post);
}
void print_arbre_post(arbre tree) { /*postfixe */
void pre(arbre tree){
if (tree->degre !=0) printf(" (");
}
void post(arbre tree){
printf(" %s", tree->name);
if (tree->degre !=0) printf(" )");
}
Recurse(tree,pre,post);
}
void print_arbre_leaf(arbre tree) { /*feuille seule*/
void pre(arbre tree){
if (tree->degre ==0) printf(" %s", tree->name);
}
Recurse(tree,pre,NULL);
}
void print_arbre_inf(arbre tree) { /*infixe */
int i;
if (tree==NULL) return;
if (tree->degre !=0) {
printf(" (");
print_arbre_inf(tree->fils[0]);
}
printf(" %s", tree->name);
for(i=1; i<tree->degre; i++)
print_arbre_inf(tree->fils[i]);
if (tree->degre !=0) printf(" )");
}
// Traversee a profondeur donné
// Evite optimasation avec queue pour parcours par niveau !!
void Recurse_prof(arbre tree, void (*PreFonct) (arbre ), int prof) {
int i;
if (tree==NULL) return;
if (prof==0) {
if (PreFonct!=NULL) PreFonct(tree);
return;
}
for(i=0; i<tree->degre; i++)
Recurse_prof(tree->fils[i],PreFonct,prof-1);
}
// impression horizontale
static void ComputeHpos(arbre tree) { /* calcule indentations des noeuds (->hpos) before printing */
/* H_PRINT_INDENT = indentation initiale en nb de char */
/* H_PRINT_TAB = espacement entre noeud en nb de char */
int indent=0;
void set_pos(arbre tree) {
int i,s;
if (tree->degre ==0)
tree->hpos=(H_PRINT_INDENT) + (H_PRINT_TAB) * indent++;
else {
for(i=0,s=0; i<tree->degre; i++)
s=s+tree->fils[i]->hpos;
tree->hpos = s / tree->degre;
}
}
Recurse(tree, NULL, set_pos);
}
// horizontal printing, par profondeur
void print_arbre_prof(arbre tree) {
char ligne[MAX_LIGNE+1]; /* one more for '\0' */
void set_car(int i, char c) {
if (i<MAX_LIGNE) ligne[i]=c; /* trunc out of line */
}
void reset_ligne() {
int j;
for (j=0; j<MAX_LIGNE; j++) set_car(j,' '); /* ligne blanche */
}
void printf_ligne() {
int j;
for (j=MAX_LIGNE-1; (j>=0) && (ligne[j]==' '); j--) set_car(j,'\0'); /* ligne justifiée */
ligne[MAX_LIGNE]='\0';
printf("%s\n",ligne);
}
int mode;
/* generation d'une ligne impression avec les noeuds a profondeur prof
mode==0, "node" N1
mode==1, "veritical1" |
mode==2, "horizontal" -------
mode==3, "vertical2" | | |
*/
void print_node(arbre tree) { /* print 1 node in ligne */
int i;
switch (mode) {
case 0: /* node */
for(i=0; tree->name[i]!='\0'; i++)
set_car(i+tree->hpos, tree->name[i]);
break;
case 1: /* vertical upper */
if (tree->degre>0)
set_car(tree->hpos,'|');
break;
case 2: /* horizontal branch */
if (tree->degre>0){
if (tree->degre==1) set_car(tree->fils[0]->hpos,'|');
else
for(i=tree->fils[0]->hpos; i<tree->fils[tree->degre-1]->hpos+1; i++)
set_car(i,'-');
}
break;
case 3: /* vertical lower */
if (tree->degre>0)
for(i=0; i<tree->degre; i++)
set_car(tree->fils[i]->hpos,'|');
break;
}
}
int i;
if (tree==NULL) return;
ComputeHpos(tree);
for (i=0; i<tree->height+1; i++) {
mode=0; reset_ligne(); Recurse_prof(tree,print_node,i); printf_ligne();
mode=1; reset_ligne(); Recurse_prof(tree,print_node,i); printf_ligne();
mode=2; reset_ligne(); Recurse_prof(tree,print_node,i); printf_ligne();
mode=3; reset_ligne(); Recurse_prof(tree,print_node,i); printf_ligne();
}
}
// Traversee a hauteur donné
void Recurse_height(arbre tree, void (*PreFonct) (arbre ), int height) {
int i;
if (tree==NULL) return;
if (tree->height==height) {
if (PreFonct!=NULL) PreFonct(tree);
return;
}
for(i=0; i<tree->degre; i++)
Recurse_height(tree->fils[i],PreFonct,height);
}
// horizontal printing, par hauteur
void print_arbre_height(arbre tree) {
char ligne[MAX_LIGNE+1]; /* one more for '\0' */
void set_car(int i, char c) {
if (i<MAX_LIGNE) ligne[i]=c; /* trunc out of line */
}
void reset_ligne() {
int j;
for (j=0; j<MAX_LIGNE; j++) set_car(j,' '); /* ligne blanche */
}
void partial_reset_ligne() {
int j;
for (j=0; j<MAX_LIGNE; j++) if (ligne[j]!='|') set_car(j,' '); /* ligne blanche */
}
void printf_ligne() {
int j;
for (j=MAX_LIGNE-1; (j>=0) && (ligne[j]==' '); j--) set_car(j,'\0'); /* ligne justifiée */
ligne[MAX_LIGNE]='\0';
printf("%s\n",ligne);
}
int mode;
/* generation d'une ligne impression avec les noeuds a meme auteur
mode==2, "horizontal" ------- |
mode==1, "vertical1" | | ou
mode==0, "node" N2 | F1 F2
mode==3, "veritical2" | | | |
*/
void print_node(arbre tree) { /* print 1 node in ligne */
int i;
switch (mode) {
case 0: /* node */
for(i=0; tree->name[i]!='\0'; i++)
set_car(i+tree->hpos, tree->name[i]);
break;
case 1: /* vertical 1 */
if (tree->degre>0)
set_car(tree->hpos,'|');
break;
case 2: /* horizontal branch */
if (tree->degre>0){
if (tree->degre==1) set_car(tree->fils[0]->hpos,'|');
else
for(i=tree->fils[0]->hpos; i<tree->fils[tree->degre-1]->hpos+1; i++)
set_car(i,'-');
}
break;
case 3: /* vertical 2 */
set_car(tree->hpos,'|');
break;
}
}
int i;
if (tree==NULL) return;
ComputeHpos(tree);
reset_ligne();
for (i=0; i<tree->height+1; i++) {
mode=2; partial_reset_ligne(); Recurse_height(tree,print_node,i); printf_ligne();
mode=1; partial_reset_ligne(); Recurse_height(tree,print_node,i); printf_ligne();
mode=0; partial_reset_ligne(); Recurse_height(tree,print_node,i); printf_ligne();
if (i<tree->height) { /* evite branche apres racine */
mode=3; partial_reset_ligne(); Recurse_height(tree,print_node,i); printf_ligne();
}
}
}
#ifdef TESTING
static void test_arbre(){
arbre arbre=NULL;
void t1(){
print_arbre(arbre); printf("\n");
print_arbre_bis(arbre); printf("\n");
print_arbre_pre(arbre); printf("\n");
print_arbre_post(arbre); printf("\n");
print_arbre_leaf(arbre); printf("\n");
print_arbre_inf(arbre); printf("\n");
printf("\n"); print_arbre_prof(arbre); printf("\n"); printf("\n");
printf("\n"); print_arbre_height(arbre); printf("\n"); printf("\n");
free_arbre(arbre); arbre=NULL;
}
arbre=new_arbre("+",new_arbre("2",NULL),new_arbre("3",NULL),NULL);
t1();
arbre=NULL;
t1();
arbre=N("R*",N("R+",F("4"),N("+"), N("R*",N("2"),N("*"),N("1"))),N("*"),N("R*",N("2"),N("*"),N("1")));
t1();
}
int main() { test_arbre(); return(0);}
#endif
Generated by GNU enscript 1.6.4.