TP6: Add ABR and tree n
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Wed, 29 Mar 2017 11:30:15 +0000 (13:30 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Wed, 29 Mar 2017 11:30:15 +0000 (13:30 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
TP6/arbres/ABR/ABR.c [new file with mode: 0644]
TP6/arbres/ABR/Makefile [new file with mode: 0644]
TP6/arbres/arbre-n-aire/Makefile [new file with mode: 0644]
TP6/arbres/arbre-n-aire/arbre_n_aire_a_completer.c [new file with mode: 0644]

diff --git a/TP6/arbres/ABR/ABR.c b/TP6/arbres/ABR/ABR.c
new file mode 100644 (file)
index 0000000..6064c00
--- /dev/null
@@ -0,0 +1,317 @@
+/*****************************************************************************/
+/*                      ABR : arbres binaires de recherche                   */
+/*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef int element;
+
+typedef struct noeud {
+ element valeur;
+ struct noeud *gauche;
+ struct noeud *droit;
+} NOEUD, *ABR;
+
+
+/* Creation d'un ABR vide */
+NOEUD *arbre_vide() 
+{
+ return NULL;
+}
+
+
+/* Insertion/Ajout d'un nouvel element dans l'ABR */
+NOEUD *insere(NOEUD *p, element x)
+{
+ if(p == NULL) 
+ {
+  p = (NOEUD *)malloc(sizeof(NOEUD));
+  p->valeur = x;
+  p->gauche = NULL;
+  p->droit = NULL;
+ }
+ else if (x == p->valeur) printf("%d est deja dans l'arbre\n",x);
+      else if (x < p->valeur)  p->gauche = insere(p->gauche,x);
+           else p->droit  = insere(p->droit,x);                          
+ return p;                       
+}
+
+
+/* Recherche d'un element dans l'ABR */
+int recherche(NOEUD *p, element x)
+{
+ if(p == NULL) return 0;
+ if(x == p->valeur) return 1;
+ if(x < p->valeur) return recherche(p->gauche,x);
+ else return recherche(p->droit,x);
+}
+
+
+/* Affichage du contenu de l'ABR en ordre croissant (par parcours profondeur infixe) */
+void affiche(NOEUD *p)
+{
+ if(p)
+ {
+  affiche(p->gauche);
+  printf("%d ",p->valeur);
+  affiche(p->droit);
+ }     
+}
+
+
+/* Affichage de l'arbre (sous forme arborescente) */
+void affiche_arbre(NOEUD *p, int col)
+{
+ int i;
+ if(p)
+ {
+  affiche_arbre(p->droit,col+1);
+  for (i=0;i<col;i++) printf("   ");
+  printf("%d\n",p->valeur);
+  affiche_arbre(p->gauche,col+1);
+ }     
+}
+
+
+/* Copie d'arbre (on cree physiquement le double de l'arbre de racine p) */
+NOEUD *copie_arbre(NOEUD *p) 
+{
+ NOEUD *q;
+ if(p == NULL) return NULL;
+ else 
+  {
+   q = (NOEUD *)malloc(sizeof(NOEUD));
+   q->valeur = p->valeur;
+   q->gauche = copie_arbre(p->gauche);
+   q->droit  = copie_arbre(p->droit);
+   return q;
+  }
+} 
+
+
+/* Destruction de l'arbre de racine p en recuperant la place occupee (free) par chacun des noeuds  */
+NOEUD *detruis_arbre(NOEUD *p)
+{
+ if(p == NULL) return p;
+ else
+  {
+   p->gauche = detruis_arbre(p->gauche);
+   p->droit  = detruis_arbre(p->droit);
+   free(p);
+   p = NULL;
+   return p;
+  }
+}
+
+
+/* Maximum d'un sous-arbre de racine p (i.e., le noeud le plus a droite) */
+NOEUD *max(NOEUD *p, NOEUD *r)
+{
+ NOEUD *q;
+ if (r->droit == NULL) 
+ {
+  p->valeur = r->valeur;
+  q = r; /* q : l'element a supprimer par free */
+  r = r->gauche;
+  free(q);
+ }
+ else r->droit = max(p,r->droit);
+ return r;
+}
+
+
+/* Suppression du noeud de valeur x dans l'arbre de racine p.
+ Suppression d'un noeud interne : la valeur du noeud a supprimer est
+ remplacee par celle du noeud le plus a droite de son sous-arbre gauche */
+NOEUD *supprime(NOEUD *p, element x)
+{
+ NOEUD *q;
+ if(p == NULL) printf("%d  n'est pas dans l'arbre\n",x);
+ else
+   if(x == p->valeur)
+     { /* suppression de p */
+      if (p->droit == NULL) {q = p ; p = p->gauche; free(q); }
+      else if (p->gauche == NULL) {q = p ; p = p->droit; free (q); }
+           else p-> gauche = max(p,p->gauche);
+     }
+   else if (x < p->valeur) p->gauche = supprime(p->gauche,x);
+        else p->droit  = supprime(p->droit,x);
+ return p;
+}
+
+
+/* Chargement d'un arbre depuis un fichier */
+NOEUD *charge(NOEUD *p, FILE *fich)
+{
+ if (p) {p = (NOEUD *)malloc(sizeof(NOEUD));
+         fread(p,sizeof(NOEUD),1,fich);
+        p->gauche = charge(p->gauche,fich);
+        p->droit =  charge(p->droit,fich);
+        }
+ return p;
+}
+
+
+/* Sauvegarde d'un arbre dans un fichier */
+NOEUD *sauve(NOEUD *p, FILE *fich)
+{
+ if (p) {fwrite(p,sizeof(NOEUD),1,fich);
+        p->gauche = sauve(p->gauche,fich);
+        p->droit =  sauve(p->droit,fich);
+        }
+ return p;
+}
+
+
+
+
+/*****************************************************************************/
+main()
+{
+ NOEUD *abr; /* on peut travailler sur 3 arbres */
+ NOEUD *abr2 = NULL;
+ char c;
+ int i, j;
+ element x;
+ char nom_fich[20];
+ FILE *fich;
+
+printf("Commandes (une lettre) possibles : v arbre_vide ; r rechercher ; i inserer ; c copier ; d detruire ; a afficher contenu ; A affiche arborescence ; s supprimer ; C charger ; S sauvegarder)\n");
+
+ do {
+     printf("Commande ? "); 
+     c = getchar();
+     switch(c)
+     {
+      case 'v' : abr = arbre_vide(); break;
+
+      case 'r' : printf("indiquer l'element a rechercher : ");
+                scanf("%d",&x);
+                 if (recherche(abr,x) == 0) printf("pas trouve\n");
+                 else printf("trouve\n"); 
+                break;
+
+      case 'i' : printf("indiquer l'element a inserer : ");
+                scanf("%d",&x); 
+                abr = insere(abr,x); 
+                break;
+
+      case 'c' : abr2 = copie_arbre(abr); 
+                break;
+
+      case 'd' : abr = detruis_arbre(abr); 
+                if(abr2) abr2 = detruis_arbre(abr2); 
+                break;
+
+      case 'a' : affiche(abr); 
+                if(abr2) {printf("\nLa copie : \n"); 
+                          affiche(abr2);}; 
+                break;
+
+      case 'A' : affiche_arbre(abr,1); 
+                if(abr2) {printf("\nLa copie : \n"); 
+                          affiche_arbre(abr2,1);}; 
+                break;     
+
+      case 's' : printf("indiquer l'element a supprimer : ");
+                scanf("%d",&x); 
+                abr = supprime(abr,x); 
+                break;
+
+      case 'C' : printf("indiquer le nom de fichier pour le chargement : ");
+                scanf("%s",nom_fich);
+                 if ((fich = fopen(nom_fich,"rb")) != NULL) 
+                 {abr =  (NOEUD *)malloc(sizeof(NOEUD));
+                  abr = charge(abr,fich);
+                  fclose(fich);
+                 };
+                break;
+      
+      case 'S' : printf("indiquer le nom de fichier pour la sauvegarde : ");
+                scanf("%s",nom_fich);
+                 if ((fich = fopen(nom_fich,"wb")) != NULL) 
+                 {abr = sauve(abr,fich);
+                  abr = NULL;
+                  fclose(fich);
+                 };  
+                break;
+
+      case 'q' : exit(0); 
+     }
+     printf("\n"); c = getchar();
+ }
+ while (1);
+}
+
+
+/* Trace d'execution **************************************    
+Commandes (une lettre) possibles : v arbre_vide ; r rechercher ; i inserer ; c copier ; d detruire ; a afficher contenu ; A affiche arborescence ; s supprimer ; C charger ; S sauvegarder)
+Commande ? v
+
+Commande ? i
+indiquer l'element a inserer : 2
+
+Commande ? i
+indiquer l'element a inserer : 6
+
+Commande ? i
+indiquer l'element a inserer : 4
+
+Commande ? i
+indiquer l'element a inserer : 5
+
+Commande ? i
+indiquer l'element a inserer : 1
+
+Commande ? i
+indiquer l'element a inserer : 0
+
+Commande ? a
+0 1 2 4 5 6 
+Commande ? A
+      6
+            5
+         4
+   2
+      1
+         0
+
+Commande ? r
+indiquer l'element a rechercher : 4
+trouve
+
+Commande ? r
+indiquer l'element a rechercher : 3
+pas trouve
+
+Commande ? s
+indiquer l'element a supprimer : 4
+
+Commande ? a
+0 1 2 5 6 
+Commande ? A
+      6
+         5
+   2
+      1
+         0
+
+Commande ? S
+indiquer le nom de fichier pour la sauvegarde : sauv.txt
+
+Commande ? C
+indiquer le nom de fichier pour le chargement : sauv.txt
+
+Commande ? a
+0 1 2 5 6 
+Commande ? A
+      6
+         5
+   2
+      1
+         0
+
+Commande ? q
+
+******************************************************************************/
diff --git a/TP6/arbres/ABR/Makefile b/TP6/arbres/ABR/Makefile
new file mode 100644 (file)
index 0000000..2a8b729
--- /dev/null
@@ -0,0 +1,79 @@
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=ABR
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+       @echo "[LD ] $@"
+       @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+       @echo "[C  ] $*"
+       @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+       @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+       @echo "[CLN]"
+       -@rm -r $(BUILDDIR)
+       -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+       objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+       objdump -t $< | sort | less
diff --git a/TP6/arbres/arbre-n-aire/Makefile b/TP6/arbres/arbre-n-aire/Makefile
new file mode 100644 (file)
index 0000000..6b0ec52
--- /dev/null
@@ -0,0 +1,79 @@
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=arbre_n_aire
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+       @echo "[LD ] $@"
+       @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+       @echo "[C  ] $*"
+       @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+       @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+clean:
+       @echo "[CLN]"
+       -@rm -r $(BUILDDIR)
+       -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+       objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+       objdump -t $< | sort | less
diff --git a/TP6/arbres/arbre-n-aire/arbre_n_aire_a_completer.c b/TP6/arbres/arbre-n-aire/arbre_n_aire_a_completer.c
new file mode 100644 (file)
index 0000000..4d4b97f
--- /dev/null
@@ -0,0 +1,178 @@
+/*****************************************************************************/\r
+/*                          arbre_n_aire.c                                   */\r
+/*     Representation d'un ensemble de mots sous forme d'arbre n-aire        */\r
+/*****************************************************************************/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+\r
+/* nombre de caracteres max dans un mot */\r
+#define N 30\r
+\r
+\r
+typedef struct noeud {\r
+ char lettre;\r
+ struct noeud *fils;\r
+ struct noeud *frere;\r
+} NOEUD;\r
+\r
+\r
+\r
+/* Recherche d'un mot dans l'arbre *****************************************/  \r
+int recherche(NOEUD *p, char *mot, int i)\r
+{\r
+ /* TODO */\r
+ return 0;\r
+}\r
+\r
+\r
+\r
+/* Creation d'une fin de mot (liste chainee suivant le lien fils) **********/\r
+NOEUD *insere_fin(char *mot, int i) /* i est l'indice de la lettre courante dans le mot */\r
+{\r
+ printf("insere_fin %c, %i\n", mot[i], i);\r
+ NOEUD *p = (NOEUD *)malloc(sizeof(NOEUD));\r
+ if(p == NULL) exit(-1);\r
+ p->lettre = mot[i]; \r
+ p->fils = NULL; \r
+ p->frere = NULL;\r
+ if(mot[i]) p->fils = insere_fin(mot, i+1);\r
+ return p;\r
+}\r
+\r
+\r
+/* Insertion d'un mot dans l'arbre ******************************************/\r
+/* (on respecte l'ordre lexicographique des freres)**************************/\r
+NOEUD *insere(NOEUD *p, char *mot, int i) /* i est l'indice de la lettre courante dans le mot */\r
+{\r
+ /* TODO */\r
+ if(p == NULL) p = insere_fin(mot, i);\r
+ return p;\r
+}\r
+\r
+          \r
+/*****************************************************************************/\r
+/* Affichage par ordre alphabetique de tous les mots stockes dans l'arbre    */\r
+void affiche(NOEUD *p, char *mot, int i) /* i est l'indice de la lettre courante dans le mot */\r
+{\r
+ /* TODO */    \r
+}\r
+\r
+\r
+/* Visualisation de l'arbre n-aire *******************************************/\r
+void affiche_arbre(NOEUD *p, int prof) /* prof est utilise pour decaller l'affichage avec des espaces  (selon le niveau dans l'arbre) */\r
+{\r
+ int i;\r
+ if(p) \r
+ {\r
+  affiche_arbre(p->frere,prof);\r
+  for (i=0;i<prof;i++) printf(" ");\r
+  printf("%c\n",p->lettre);\r
+  affiche_arbre(p->fils,prof+1);\r
+ }\r
+}\r
+\r
+\r
+/* Suppression d'un mot de l'arbre ********************************************/\r
+/* Attention a ne supprimer que la fin du mot qui n'est partagee par aucun autre mot de l'arbre */\r
+NOEUD *supprime(NOEUD *p, char *mot, int i) /* i est l'indice de la lettre courante dans le mot */\r
+{\r
+ /* TODO */\r
+ return p;\r
+}\r
+\r
+\r
+\r
+/* Chargement des mots d'un fichier (vu comme un dictionnaire) dans l'arbre **/\r
+NOEUD *charge_dico(char *nom_fichier, int *nb_mots)\r
+{\r
+ NOEUD *p;\r
+ FILE *fp;\r
+ char mot[N];\r
+ int i;\r
+       \r
+ p = NULL;     \r
+ fp = fopen(nom_fichier,"rt");\r
+ if (fp == NULL) exit(-1);\r
+ fscanf(fp,"%d",nb_mots); /* sur la 1ere ligne du fichier, le nombre de mots */\r
+ for (i=0; i< *nb_mots; i++) \r
+  {\r
+   fscanf(fp,"%s",mot);\r
+   p = insere(p, mot, 0); /* TODO il faut finir "insere" pour que "charge_dico" fonctionne */\r
+  }\r
+ fclose(fp);\r
+ return p;\r
+}\r
+\r
+\r
+\r
+/* Ecriture dans fp de tous les mots stockes dans l'arbre ********************/\r
+void affiche_fich(FILE *fp, NOEUD *p, char *mot, int i)\r
+{      \r
+ /* TODO */\r
+ /* ressemble beaucoup a "affiche", avec le parametre en plus "fp" qui est un FILE* */\r
+}\r
+\r
+\r
+/* Sauvegarde des mots de l'arbre dans un fichier ****************************/\r
+void sauve_dico(NOEUD *p, char *nom_fichier, int nb_mots)\r
+{\r
+ FILE *fp;\r
+ char mot[N];\r
+       \r
+ fp = fopen(nom_fichier,"wt");\r
+ if (fp == NULL) exit(-1);\r
+ fprintf(fp,"%d\n",nb_mots);\r
+ affiche_fich(fp,p,mot,0); /* TODO il faut finir la fonction "affiche_fich" pour que "sauve_dico" fonctionne */\r
+ fclose(fp);\r
+}\r
+\r
+\r
+\r
+\r
+/*****************************************************************************/\r
+int main(int argc, char *argv[])\r
+{\r
+ char mot[N];\r
+ NOEUD *arbre = NULL;\r
+\r
+ printf("saisir un mot : ");\r
+ gets(mot); \r
+\r
+ printf("\ninsertion de %s\n", mot);\r
+ arbre = insere(arbre, mot, 0);\r
+\r
+ printf("\naffichage arbre :\n");\r
+ affiche_arbre(arbre, 0);\r
+\r
+ /* TODO */\r
+\r
+}\r
+\r
+\r
+\r
+/* Exemple de trace d'execution *************************\r
+\r
+saisir un mot : salut\r
+\r
+insertion de salut\r
+insere_fin s, 0\r
+insere_fin a, 1\r
+insere_fin l, 2\r
+insere_fin u, 3\r
+insere_fin t, 4\r
+insere_fin , 5\r
+\r
+affichage arbre :\r
+s\r
+ a\r
+  l\r
+   u\r
+    t\r
+     \r
+... TODO ...\r
+\r
+**********************************************************/    \r
+\r