diff --git a/source_codes/arbres_AVL/avl.adb b/source_codes/arbres_AVL/avl.adb new file mode 100644 index 0000000000000000000000000000000000000000..b0e1e42d683bb85e5f2cf87deee91dea541231c9 --- /dev/null +++ b/source_codes/arbres_AVL/avl.adb @@ -0,0 +1,323 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure avl is + -- paquetage pour l'�criture en x-�me ligne et y-�me colonne + package Entier_ES is new Integer_IO(Integer); + use Entier_ES; + + Niv_Max : constant := 6; + + subtype T_Donnee is Integer; + + type T_Noeud; + type T_Arbre is access T_Noeud; + type T_Noeud is record + Cle : T_Donnee; + Gauche,Droite : T_Arbre; + Hg,Hd : Natural := 0; + end record; + + Cle_Presente : exception; + +------------------------------------------------------------ +-- fonction qui donne le nombre max entre 2 nombres -- +------------------------------------------------------------ + function Max(H1,H2 : Integer) return Integer is + begin + if H1 > H2 then + return H1; + else + return H2; + end if; + end Max; + +------------------------------------------------------------ +-- fonction qui retourne le premier noeud d�s�quilibr� et -- +-- met � jour les hauteurs sur le chemin d'insertion -- +------------------------------------------------------------ + function Desequilibre(Arbre : in T_Arbre; + Donnee : in T_Donnee) return T_Arbre is + Temp : T_Arbre := Arbre; + Parent : T_Arbre; + Hd_Prec,Hg_Prec : Integer := 0; + begin + while Temp.Cle /= Donnee loop + if abs(Temp.Hd - Temp.Hg) = 2 then + Parent := Temp; + Hd_Prec := Parent.Hd; + Hg_Prec := Parent.Hg; + if Donnee <= Parent.Cle then + Parent.Hg := Parent.Hg - 1; + else + Parent.Hd := Parent.Hd - 1; + end if; + end if; + if Donnee <= Temp.Cle then + Temp := Temp.Gauche; + else + Temp := Temp.Droite; + end if; + end loop; + if Parent /= null then + Parent.Hd := Hd_Prec; + Parent.Hg := Hg_Prec; + end if; + return Parent; + end Desequilibre; + + procedure Imprimer(Arbre : in T_Arbre; N : in Positive) is + begin + if Arbre /= null then + Imprimer(Arbre.Droite,N+1); + for I in 1..N loop + Put(" "); + end loop; + Put(Arbre.Cle); + Put("(" & Integer'Image(Arbre.Hg) & "," & Integer'Image(Arbre.hd) & ")"); + New_Line; + Imprimer(Arbre.Gauche,N+1); + end if; + end Imprimer; + +------------------------------------------------------------ +-- fonction qui calcule les hauteurs d'un arbre -- +------------------------------------------------------------ + function Hauteur(Noeud : in T_Arbre) return Natural is + begin + if Noeud = null then + return 0; + else + return 1+Max(Hauteur(Noeud.Gauche),Hauteur(Noeud.Droite)); + end if; + end Hauteur; + +------------------------------------------------------------ +-- procedure qui remet � jour les hauteurs des noeuds -- +-- apr�s le r��quilibrage -- +------------------------------------------------------------ + procedure Hauteurs(Noeud : in T_Arbre) is + begin + if Noeud.Gauche /= null then + Hauteurs(Noeud.Gauche); + Noeud.Hg := 1+Max(Noeud.Gauche.Hg,Noeud.Gauche.Hd); + else + Noeud.Hg := 0; + end if; + if Noeud.Droite /= null then + Hauteurs(Noeud.Droite); + Noeud.Hd := 1+Max(Noeud.Droite.Hg,Noeud.Droite.Hd); + else + Noeud.Hd := 0; + end if; + end Hauteurs; + +------------------------------------------------------------ +-- procedure qui remet � jour les hauteurs des noeuds -- +-- apr�s le r��quilibrage -- +------------------------------------------------------------ + procedure Hauteur_Noeud(Noeud : in T_Arbre) is + begin + if Noeud.Gauche /= null then + Noeud.Hg := 1+Max(Noeud.Gauche.Hg,Noeud.Gauche.Hd); + else + Noeud.Hg := 0; + end if; + if Noeud.Droite /= null then + Noeud.Hd := 1+Max(Noeud.Droite.Hg,Noeud.Droite.Hd); + else + Noeud.Hd := 0; + end if; + end Hauteur_Noeud; + +------------------------------------------------------------ +-- fonction qui effectue une rotation gauche sur le -- +-- noeud d�s�quilibr� -- +------------------------------------------------------------ + function Rot_G(P : T_Arbre) return T_Arbre is + Q : T_Arbre := null; + begin + if P /= null then + Q := P.Droite; + P.Droite := Q.Gauche; + Q.Gauche := P; + Hauteur_Noeud(P); + Hauteur_Noeud(Q); + end if; + return Q; + end Rot_G; + +------------------------------------------------------------ +-- fonction qui effectue une rotation droite sur le -- +-- noeud d�s�quilibr� -- +------------------------------------------------------------ + function Rot_D(P : T_Arbre) return T_Arbre is + Q : T_Arbre := null; + begin + if P /= null then + Q := P.Gauche; + P.Gauche := Q.Droite; + Q.Droite := P; + Hauteur_Noeud(P); + Hauteur_Noeud(Q); + end if; + return Q; + end Rot_D; + +------------------------------------------------------------ +-- procedure qui effectue une double rotation gauche -- +-- droite sur le noeud d�s�quilibr� -- +------------------------------------------------------------ + function Rot_GD(Noeud : T_Arbre) return T_Arbre is + begin + Noeud.Gauche := Rot_G(Noeud.Gauche); + return Rot_D(Noeud); + end Rot_GD; + +------------------------------------------------------------ +-- procedure qui effectue une rotation gauche sur le -- +-- noeud d�s�quilibr� -- +------------------------------------------------------------ + procedure Rotation_G(Noeud : in T_Arbre) is + New_Noeud : T_Arbre; + begin + New_Noeud := new T_Noeud'(Noeud.Cle, + Noeud.Gauche, + Noeud.Droite.Gauche, + 0,0); + Noeud.Cle := Noeud.Droite.Cle; + Noeud.Gauche := New_Noeud; + Noeud.Droite := Noeud.Droite.Droite; + Hauteur_Noeud(New_Noeud); + Hauteur_Noeud(Noeud); + end Rotation_G; + + + + + +------------------------------------------------------------ +-- procedure qui effectue une double rotation droite -- +-- gauche sur le noeud d�s�quilibr� -- +------------------------------------------------------------ + procedure Rot_DG(Noeud : in T_Arbre) is + begin + Noeud.Droite := Rot_D(Noeud.Droite); + return Rot_G(Noeud); + end Rot_DG; + +------------------------------------------------------------ +-- procedure qui effectue une rotation droite sur le -- +-- noeud d�s�quilibr� -- +------------------------------------------------------------ + procedure Rotation_D(Noeud : in T_Arbre) is + New_Noeud : T_Arbre; + begin + New_Noeud := new T_Noeud'(Noeud.Cle, + Noeud.Gauche.Droite, + Noeud.Droite, + 0,0); + Noeud.Cle := Noeud.Gauche.Cle; + Noeud.Droite := New_Noeud; + Noeud.Gauche := Noeud.Gauche.Gauche; + Hauteur_Noeud(New_Noeud); + Hauteur_Noeud(Noeud); + end Rotation_D; + +------------------------------------------------------------ +-- procedure qui effectue une double rotation gauche -- +-- droite sur le noeud d�s�quilibr� -- +------------------------------------------------------------ + procedure Rotation_GD(Noeud : in T_Arbre) is + begin + Rotation_G(Noeud.Gauche); + Rotation_D(Noeud); + end Rotation_GD; + +------------------------------------------------------------ +-- procedure qui effectue une double rotation droite -- +-- gauche sur le noeud d�s�quilibr� -- +------------------------------------------------------------ + procedure Rotation_DG(Noeud : in T_Arbre) is + begin + Rotation_D(Noeud.Droite); + Rotation_G(Noeud); + end Rotation_DG; + +------------------------------------------------------------ +-- procedure qui r��quilibre l'arbre -- +------------------------------------------------------------ + procedure Reequilibre(Noeud : in T_Arbre) is + begin + case (Noeud.Hd - Noeud.Hg) is + when +2 => + case (Noeud.Droite.Hd - Noeud.Droite.Hg) is + when +1 => Rotation_G(Noeud); + when others => Rotation_DG(Noeud); + end case; + when others => + case (Noeud.Gauche.Hd - Noeud.Gauche.Hg) is + when -1 => Rotation_D(Noeud); + when others => Rotation_GD(Noeud); + end case; + end case; + end Reequilibre; + +------------------------------------------------------------ +-- procedure qui ins�re une valeur dans l'arbre -- +------------------------------------------------------------ + procedure Insertion(Donnee : in T_Donnee; + Arbre : in out T_Arbre; + Deseq : in out T_Arbre) is + begin + if Arbre = null then + Arbre := new T_Noeud'(Donnee,null,null,0,0); + Deseq := null; + else + if Donnee = Arbre.Cle then + raise Cle_Presente; + elsif Donnee < Arbre.Cle then + Insertion(Donnee, Arbre.Gauche,Deseq); + if Deseq = null then + Arbre.Hg := 1 + Max(Arbre.Gauche.Hg,Arbre.Gauche.Hd); + end if; + else + Insertion(Donnee, Arbre.Droite,Deseq); + if Deseq = null then + Arbre.Hd := 1 + Max(Arbre.Droite.Hg,Arbre.Droite.Hd); + end if; + end if; + if abs(Arbre.Hd - Arbre.Hg) = 2 and Deseq = null then + Deseq := Arbre; + end if; + end if; + end Insertion; + +-- Procedure principale + Mon_Arbre : T_Arbre; + Str : String(1..80) := (others => Ascii.Nul); + Taille : Natural; + Nb : Integer; + Deseq : T_Arbre; + +begin + loop + begin + Put("Nombre: "); + Get_Line(Str,Taille); + exit when Taille = 0; + Nb := Integer'Value(Str(1..Taille)); + Insertion(Nb,Mon_Arbre,Deseq); + if Deseq /= null then + Put_Line("Desequilibre!"); + Reequilibre(Deseq); + end if; + New_Line; + --Hauteurs(Mon_Arbre); + Imprimer(Mon_Arbre,1); + New_Line; + exception + when Cle_Presente => + Put_Line("Cl� d�j� pr�sente!"); + end; + end loop; +end avl; diff --git a/source_codes/arbres_AVL/avl.c b/source_codes/arbres_AVL/avl.c new file mode 100644 index 0000000000000000000000000000000000000000..4c5cbce1aa7d1ffab08e85141f009e98f29a72bd --- /dev/null +++ b/source_codes/arbres_AVL/avl.c @@ -0,0 +1,174 @@ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <assert.h> +#include <stdbool.h> +#include "avl.h" + +void avl_print(arbre tree,int N) { + if (N <= 0) { + N = 1; + } + if (NULL != tree) { + avl_print(tree->child[1],N+2); + for (int i=0;i<N;i++) { + printf(" "); + } + printf("%d\n",tree->key); + avl_print(tree->child[0],N+2); + } +} + +node* avl_desequilibre(arbre tree,clef key) { + node* crt = tree; + node* parent = NULL; + int h_prec[2] = {0,0}; + + while (NULL != crt && crt->key != key) { + if (abs(crt->h[1]-crt->h[0]) == 2) { + parent = crt; + h_prec[0] = parent->h[0]; + h_prec[1] = parent->h[1]; + parent->h[key > parent->key] -= 1; + } + crt = crt->child[key > crt->key]; + } + if (NULL != parent) { + parent->h[0] = h_prec[0]; + parent->h[1] = h_prec[1]; + } + return parent; +} + +int avl_height(arbre tree) { + if (NULL == tree) { + return 0; + } else { + return 1+fmax(avl_height(tree->child[0]),avl_height(tree->child[1]))+0.01; + } +} + +void avl_heights(arbre tree) { + for (int i=0;i<2;i++) { + if (NULL != tree->child[i]) { + avl_heights(tree->child[i]); + tree->h[i] = 1+fmax(tree->child[i]->h[0],tree->child[i]->h[1])+0.01; + } else { + tree->h[i] = 0; + } + } +} + +void avl_height_node(node* nd) { + for (int i=0;i<2;i++) { + if (NULL != nd->child[i]) { + nd->h[i] = 1+fmax(nd->child[i]->h[0],nd->child[i]->h[1])+0.01; + } else { + nd->h[i] = 0; + } + } +} + +static node* avl_rot(node* P,bool right) { + node* Q = NULL; + if (NULL != P) { + Q = P->child[right]; + P->child[right] = Q->child[!right]; + Q->child[!right] = P; + avl_height_node(P); + avl_height_node(Q); + } + return Q; +} + +node* avl_rot_g(node* nd) { + return avl_rot(nd,false); +} + +node* avl_rot_d(node* nd) { + return avl_rot(nd,true); +} + +static node* avl_rot2(node* nd,bool dg) { + nd->child[dg] = avl_rot(nd->child[dg],dg); + return avl_rot(nd,!dg); +} + +node* avl_rot_gd(node* nd) { + return avl_rot2(nd,false); +} + +node* avl_rot_dg(node* nd) { + return avl_rot2(nd,true); +} + +static void avl_rotation(node* nd,bool right) { + node* new_nd = calloc(1,sizeof(node)); + new_nd->key = nd->key; + new_nd->child[right] = nd->child[right]; + new_nd->child[!right] = nd->child[!right]->child[right]; + node* tmp = nd->child[!right]; + + nd->key = nd->child[!right]->key; + nd->child[right] = new_nd; + nd->child[!right] = nd->child[!right]->child[!right]; + avl_height_node(new_nd); + avl_height_node(nd); + free(tmp); +} + +void avl_rotation_g(node* nd) { + avl_rotation(nd,false); +} + +void avl_rotation_d(node* nd) { + avl_rotation(nd,true); +} + +static void avl_rotation2(node* nd,bool dg) { + avl_rotation(nd->child[dg],dg); + avl_rotation(nd,!dg); +} + +void avl_rotation_gd(node* nd) { + avl_rotation2(nd,false); +} + +void avl_rotation_dg(node* nd) { + avl_rotation2(nd,true); +} + +void avl_reequilibre(node* nd) { + switch(nd->h[1]-nd->h[0]) { + case +2: + switch(nd->child[1]->h[1] - nd->child[1]->h[0]) { + case +1: avl_rotation_g(nd); break; + case -1: avl_rotation_dg(nd); + } + break; + case -2: + switch(nd->child[0]->h[1] - nd->child[0]->h[0]) { + case -1: avl_rotation_d(nd); break; + case +1: avl_rotation_gd(nd); + } + } +} + +void avl_insert(clef key,arbre* tree,arbre* deseq) { + if (NULL == *tree) { + *tree = calloc(1,sizeof(node)); + (*tree)->key = key; + *deseq = NULL; + } else { + avl_insert(key,&((*tree)->child[key > (*tree)->key]),deseq); + if (NULL == *deseq) { + (*tree)->h[key > (*tree)->key] + = 1+fmax((*tree)->child[key > (*tree)->key]->h[0], + (*tree)->child[key > (*tree)->key]->h[1]); + } + if (abs((*tree)->h[1]-(*tree)->h[0]) == 2 && NULL == *deseq) { + *deseq = *tree; + } + } +} + diff --git a/source_codes/arbres_AVL/avl.h b/source_codes/arbres_AVL/avl.h new file mode 100644 index 0000000000000000000000000000000000000000..9f31a45de877550098b9ace6e2447bcb0e08a21b --- /dev/null +++ b/source_codes/arbres_AVL/avl.h @@ -0,0 +1,87 @@ +#ifndef AVL_H +#define AVL_H + +typedef int clef; + +typedef struct _node { + clef key; + struct _node* child[2]; + int h[2]; +} node; + +typedef node* arbre; + +//---------------------------------------------------------- +// fonction qui imprime un arbre -- +//---------------------------------------------------------- +void avl_print(arbre tree,int N); +//---------------------------------------------------------- +// fonction qui retourne le premier noeud d�s�quilibr� et -- +// met � jour les hauteurs sur le chemin d'insertion -- +//---------------------------------------------------------- +node* avl_desequilibre(arbre tree,clef key); +//---------------------------------------------------------- +// fonction qui calcule la hauteur d'un arbre -- +//---------------------------------------------------------- +int avl_height(arbre tree); +//---------------------------------------------------------- +// fonction qui remet � jour les hauteurs des noeuds -- +// apr�s le r��quilibrage -- +//---------------------------------------------------------- +void avl_heights(arbre tree); +//---------------------------------------------------------- +// fonction qui remet � jour les hauteurs des noeuds -- +// apr�s le r��quilibrage -- +//---------------------------------------------------------- +void avl_height_node(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une rotation gauche sur le -- +// noeud d�s�quilibr� -- +//---------------------------------------------------------- +node* avl_rot_g(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une rotation droite sur le -- +// noeud d�s�quilibr� -- +//---------------------------------------------------------- +node* avl_rot_d(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une double rotation gauche -- +// droite sur le noeud d�s�quilibr� -- +//---------------------------------------------------------- +node* avl_rot_gd(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une double rotation droite -- +// gauche sur le noeud d�s�quilibr� -- +//---------------------------------------------------------- +node* avl_rot_dg(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une rotation gauche sur le -- +// noeud d�s�quilibr� -- +//---------------------------------------------------------- +void avl_rotation_g(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une rotation droite sur le -- +// noeud d�s�quilibr� -- +//---------------------------------------------------------- +void avl_rotation_d(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une double rotation gauche -- +// droite sur le noeud d�s�quilibr� -- +//---------------------------------------------------------- +void avl_rotation_gd(node* nd); +//---------------------------------------------------------- +// fonction qui effectue une double rotation droite -- +// gauche sur le noeud d�s�quilibr� -- +//---------------------------------------------------------- + void avl_rotation_dg(node* nd); +//---------------------------------------------------------- +// fonction qui r��quilibre l'arbre -- +//---------------------------------------------------------- +void avl_reequilibre(node* nd); +//---------------------------------------------------------- +// fonction qui ins�re une valeur dans l'arbre -- +//---------------------------------------------------------- +void avl_insert(clef key,arbre* tree, arbre* deseq); + +#endif + diff --git a/source_codes/arbres_AVL/bin_tree.c b/source_codes/arbres_AVL/bin_tree.c new file mode 100644 index 0000000000000000000000000000000000000000..5a38e140a09d76ed2fb3c03acdd4419cde92b784 --- /dev/null +++ b/source_codes/arbres_AVL/bin_tree.c @@ -0,0 +1,127 @@ +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <stdbool.h> +#include <math.h> +#include "bin_tree.h" + +static node* position(arbre tree,int cle) { + node* crt = tree; + if (NULL != crt) { + while (cle != crt->key + && NULL != crt->child[(cle > crt->key)]) { + crt = crt->child[(cle > crt->key)]; + } + } + return crt; +} + +int arbre_depth(arbre tree) { + if (NULL == tree) { + return 0; + } else { + return 1+fmax(arbre_depth(tree->child[0]),arbre_depth(tree->child[1])); + } +} + +int arbre_size(arbre tree) { + if (NULL == tree) { + return 0; + } else { + return 1+arbre_size(tree->child[0])+arbre_size(tree->child[1]); + } +} + +bool arbre_insert(arbre* tree,int cle) { + if (NULL == *tree) { + *tree = calloc(1,sizeof(node)); + (*tree)->key = cle; + } else { + node* nd = position(*tree,cle); + if (cle != nd->key) { + nd->child[(cle > nd->key)] = calloc(1,sizeof(node)); + nd->child[(cle > nd->key)]->key = cle; + } else { + return false; + } + } + return true; +} + +static node* parent(arbre tree,node* nd) { + assert(NULL != tree && NULL != nd); + node* parent = NULL; + if (nd != tree) { + node* crt = tree; + int cle = nd->key; + do { + parent = crt; + if (cle != crt->key) { + crt = crt->child[(cle > crt->key)]; + } + } while (crt != nd); + } + return parent; +} + + + + + + + +bool arbre_delete(arbre* tree,int cle) { + node* nd = position(*tree,cle); + + if (NULL == nd || cle != nd->key) { + return false; + } + + // terminal node + if (NULL == nd->child[0] && NULL == nd->child[1]) { + node* nd_parent = parent(*tree,nd); + if (NULL == nd_parent) { // single node tree + *tree = NULL; + } else { + nd_parent->child[(nd == nd_parent->child[1])] = NULL; + } + free(nd); + return true; + } + + for (int ind=0;ind<2;ind++) { + if (NULL != nd->child[ind]) { + node* next = position(nd->child[ind],cle); + int val = next->key; + if (NULL == nd->child[ind]->child[ind^1]) { + nd->child[ind] = next->child[ind]; + free(next); + } else { + bool res = arbre_delete(tree,next->key); + } + nd->key = val; + return true; + } + } +} + +void arbre_print(arbre tree,int N) { + if (N <= 0) { + N = 1; + } + if (NULL != tree) { + arbre_print(tree->child[1],N+1); + for (int i=0;i<N;i++) { + printf(" "); + } + printf("%d\n",tree->key); + arbre_print(tree->child[0],N+1); + } +} + +bool arbre_search(arbre tree,int cle) { + node* nd = position(tree,cle); + return (NULL != nd && cle == nd->key); +} + + diff --git a/source_codes/arbres_AVL/bin_tree.h b/source_codes/arbres_AVL/bin_tree.h new file mode 100644 index 0000000000000000000000000000000000000000..25843d5df1a9430ea0d58997f84289b166b5dcc8 --- /dev/null +++ b/source_codes/arbres_AVL/bin_tree.h @@ -0,0 +1,39 @@ +#ifndef BIN_TREE_H +#define BIN_TREE_H + +// Structure pour un arbre binaire +typedef int cle; +typedef struct _node { + cle key; + struct _node* child[2]; +} node; +typedef node* arbre; + +// Fonctionnalités pour un arbre binaire ordonné +bool arbre_search(arbre tree,int cle); +bool arbre_insert(arbre* tree,int cle); +bool arbre_delete(arbre* tree,int cle); +void arbre_print(arbre tree,int N); +int arbre_depth(arbre tree); +int arbre_size(arbre tree); +#endif + + + + + + + + + + + + + + + + + + + + diff --git a/source_codes/arbres_AVL/main.c b/source_codes/arbres_AVL/main.c new file mode 100644 index 0000000000000000000000000000000000000000..3454c3982330b2606b2b840f92f9b46a7bb396e4 --- /dev/null +++ b/source_codes/arbres_AVL/main.c @@ -0,0 +1,25 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> +#include <stdbool.h> +#include "avl.h" + +void main() { + arbre mon_arbre = NULL, deseq = NULL; + char nbr[20]; + while (true) { + printf("Nombre: "); + scanf("%s",nbr); + if (strcmp(nbr,"quit") == 0) break; + avl_insert(atoi(nbr),&mon_arbre,&deseq); + if (NULL != deseq) { + printf("Desequilibre!"); + avl_reequilibre(deseq); + } + printf("\n\n"); + avl_print(mon_arbre,1); + printf("\n\n"); + } +}