suivant: Knapsack par recherche exhaustive
monter: Corrigés des programmes
précédent: Tas binomiaux
Table des matières
avl.c
#include<stdio.h>
#include<malloc.h>
#include"avl.h"
/*------------------------------------------------------*/
/*
Noeud de l'ABR.
*/
typedef struct nd
{
/*
key est la cle du noeud courant.
*/
int key;
/*
pointeur vers l'element de cle key
*/
void* data;
/*
hauteur du sous-arbre :
0 si ce noeud est une feuille.
*/
int height;
/*
Pointeur vers le sous-arbre droit.
*/
struct nd * left;
/*
Pointeur vers le sous-arbre gauche.
*/
struct nd * right;
}node;
/*------------------------------------------------------*/
/*
Retourne la hauteur de l'arbre de racine l,
-1 si l est vide.
*/
int getHeight(node* l)
{
if (l == NULL)
return -1;
return l->height;
}
/*------------------------------------------------------*/
/*
Retourne la plus grande des deux valeurs i et j.
*/
int max(int i, int j)
{
if (i < j)
return j;
return i;
}
/*------------------------------------------------------*/
/*
Met a jour la hauteur de la racine l en fonction des
hauteurs des racines des deux sous-arbres.
*/
void setHeight(node* l)
{
if (l != NULL)
{
l->height = 1 + max(getHeight(l->left), getHeight(l->right));
}
}
/*------------------------------------------------------*/
/*
Cree un noeud contenant la donnee data,
ayant pour sous-arbre gauche l et
pour sous-arbre droit r.
*/
node* nodeCreate(int (*getKey)(void*), node* l, void* data, node* r)
{
node* n = (node*)malloc(sizeof(node));
if (n == NULL)
error();
n->data = data;
n->left = l;
n->right = r;
n->key = getKey(data);
setHeight(n);
return n;
}
/*------------------------------------------------------*/
/*
Retourne un avl vide
*/
avl* avlCreate(int (*getKey)(void*), void (*freeData)(void*))
{
avl* a = (avl*)malloc(sizeof(avl));
if (!a)
error();
a->getKey = getKey;
a->freeData = freeData;
a->root = NULL;
return a;
}
/*------------------------------------------------------*/
/*
Fait de freeData la fonction de destruction des donnees.
*/
void avlSetFreeFunction(avl* a, void (*freeData)(void*))
{
a->freeData = freeData;
}
/*------------------------------------------------------*/
/*
Affiche toutes les cles du sous-arbre de racine n dans
l'ordre croissant.
*/
void nodePrintKeys(node* n)
{
if(n)
{
printf("(");
nodePrintKeys(n->left);
printf(", %d, ", n->key );
nodePrintKeys(n->right);
printf(")");
}
}
/*------------------------------------------------------*/
/*
Affiche pour tous les noeuds du sous-arbre de racine n
la difference entre les hauteurs du sous-arbre droit et
gauche.
*/
void nodePrintLevels(node* n)
{
if(n)
{
printf("(");
nodePrintLevels(n->left);
printf(", %d, ", getHeight(n->left)- getHeight(n->right));
nodePrintLevels(n->right);
printf(")");
}
}
/*------------------------------------------------------*/
/*
Effectue une rotation droite de l'arbre de racine x,
retourne la racine de l'arbre apres rotation.
*/
node* rotateRight(node* x)
{
node* y = x->left;
node* b = y->right;
y->right = x;
x->left = b;
setHeight(x);
setHeight(y);
return y;
}
/*------------------------------------------------------*/
/*
Effectue une rotation gauche de l'arbre de racine x,
retourne la racine de l'arbre apres rotation.
*/
node* rotateLeft(node* x)
{
node* y = x->right;
node* b = y->left;
y->left = x;
x->right = b;
setHeight(x);
setHeight(y);
return y;
}
/*------------------------------------------------------*/
/*
Effectue une rotation gauche-droite de l'arbre de racine x,
retourne la racine de l'arbre apres rotation.
*/
node* rotateLeftRight(node* x)
{
x->left = rotateLeft(x->left);
return rotateRight(x);
}
/*------------------------------------------------------*/
/*
Effectue une rotation droite-gauche de l'arbre de racine x,
retourne la racine de l'arbre apres rotation.
*/
node* rotateRightLeft(node* x)
{
x->right = rotateRight(x->right);
return rotateLeft(x);
}
/*------------------------------------------------------*/
/*
Reequilibre l'arbre de racine x, retourne la racine de
l'arbre apres reequilibrage. On part du principe
que les hauteurs des sous-arbres droit et gauche different
de au plus 1.
*/
node* balance(node* x)
{
if (x != NULL)
{
setHeight(x);
if (getHeight(x->left) + 2 == getHeight(x->right))
{
if(getHeight(x->left) + 1 == getHeight(x->right->right))
return rotateLeft(x);
else
return rotateRightLeft(x);
}
if (getHeight(x->left) == getHeight(x->right) + 2)
{
if(getHeight(x->left->left) == getHeight(x->right) + 1)
return rotateRight(x);
else
return rotateLeftRight(x);
}
}
return x;
}
/*------------------------------------------------------*/
/*
Insere la donnee v dans l'arbre de racine n
et reequilibre l'arbre, retourne la racine de
l'arbre apres insertion et reequilibrage.
*/
node* nodeInsert(int (*key)(void*), node* n, void* v)
{
if(n == NULL)
return nodeCreate(key, NULL, v, NULL);
if(key(v) == n->key)
return n;
if(key(v) < n->key)
n->left = nodeInsert(key, n->left, v);
else
n->right = nodeInsert(key, n->right, v);
return balance(n);
}
/*------------------------------------------------------*/
/*
Insere la donnee v dans l'arbre a, O(log n).
*/
void avlInsert(avl* a, void* v)
{
a->root = nodeInsert(a->getKey, (node*)a->root, v);
}
/*------------------------------------------------------*/
/*
Affiche les cles de l'AVL a dans l'ordre croissant, O(n)
*/
void avlPrintKeys(avl* a)
{
nodePrintKeys((node*)a->root);
printf("\n");
}
/*------------------------------------------------------*/
/*
Affiche pour chaque noeud la difference entre les hauteurs
des sous-arbres droit et gauche de l'AVL.
*/
void avlPrintLevels(avl* a)
{
nodePrintLevels((node*)a->root);
printf("\n");
}
/*------------------------------------------------------*/
/*
Retourne la donnee de cle k si elle se trouve dans le sous-arbre
de racine n, NULL sinon.
*/
void* findNode(node* n, int k)
{
if (n == NULL)
return NULL;
if (n->key == k)
return n->data;
if (k < n->key)
return findNode(n->left, k);
else
return findNode(n->right, k);
}
/*------------------------------------------------------*/
/*
Retourne la donnee de cle x si elle se trouve dans l'AVL a,
NULL sinon, O(log n)
*/
void* avlFind(avl* a, int x)
{
return findNode((node*)a->root, x);
}
/*------------------------------------------------------*/
/*
Fait pointer *max vers le noeud de cle maximale dans
le sous-arbre de racine n, detache le noeud *max de l'arbre
et retourne la racine de l'arbre apres suppression.
*/
node* removeMax(node* n, node** max)
{
if (n == NULL)
{
*max = NULL;
return NULL;
}
if (n->right == NULL)
{
*max = n;
return NULL;
}
n->right = removeMax(n->right, max);
return balance(n);
}
/*------------------------------------------------------*/
/*
Fait pointer *min vers le noeud de cle minimale dans
le sous-arbre de racine n, detache le noeud *min de l'arbre
et retourne la racine de l'arbre apres suppression.
*/
node* removeMin(node* n, node** min)
{
if (n == NULL)
{
*min = NULL;
return NULL;
}
if (n->left == NULL)
{
*min = n;
return NULL;
}
n->left = removeMin(n->left, min);
return balance(n);
}
/*------------------------------------------------------*/
/*
Supprime le noeud de cle k du sous-arbre de racine n,
applique la fonction de destruction a la donnee de ce noeud,
et retourne la racine de l'arbre apres la suppression.
*/
node* removeNode(node* n, int k, void (*freeData)(void*))
{
node* p;
if (n == NULL)
return NULL;
if (k == n->key)
{
p = NULL;
n->left = removeMax(n->left, &p);
if (p == NULL)
n->right = removeMin(n->right, &p);
if (p != NULL)
{
p->left = n->left;
p->right = n->right;
}
freeData(n->data);
free(n);
return balance(p);
}
if (k < n->key)
n->left = removeNode(n->left, k, freeData);
else
n->right = removeNode(n->right, k, freeData);
return balance(n);
}
/*------------------------------------------------------*/
/*
Supprime le noeud de cle k de l'AVL a, applique la fonction
de destruction a la donnee de cle k, O(log n).
*/
void avlRemove(avl* a, int k)
{
a->root = removeNode((node*)a->root, k, a->freeData);
}
/*------------------------------------------------------*/
/*
Place dans la liste chainee l toutes les donnees
du sous-arbre de racine n dans l'ordre croissant.
*/
void nodeToList(node* n, linkedList* l)
{
if (n != NULL)
{
nodeToList(n->left, l);
linkedListAppend(l, n->data);
nodeToList(n->right, l);
}
}
/*------------------------------------------------------*/
/*
Retourne une liste chainee contenant toutes les donnees
de l'AVL a disposees dans l'ordre croissant, O(n).
*/
linkedList* avlToList(avl* a)
{
linkedList* l = linkedListCreate();
nodeToList((node*)a->root, l);
return l;
}
/*------------------------------------------------------*/
/*
Detruit tous les noeuds du sous-arbre de racine n,
applique la fonction de destruction fr a toutes les
donnees du sous-arbre.
*/
void nodeDestroy(node* n, void (*fr)(void*))
{
if (n != NULL)
{
nodeDestroy(n->left, fr);
nodeDestroy(n->right, fr);
fr(n->data);
free(n);
}
}
/*------------------------------------------------------*/
/*
Detruit l'AVL a, applique la fonction de destruction a
toutes les donnees du sous-arbre, O(n).
*/
void avlDestroy(avl* a)
{
nodeDestroy((node*)a->root, a->freeData);
free(a);
}
/*------------------------------------------------------*/
/*------------------------------------------------------*/
/*
Pour tester les algorithmes
*/
void destroyInt(void* i)
{
free((int*)i);
}
int getIntKey(void* i)
{
return *((int*)i);
}
void doNothing()
{
}
int main()
{
int i;
int* d;
linkedList* l;
link* m;
avl* a = avlCreate(getIntKey, destroyInt);
for (i = 0 ; i < 40 ; i++)
{
d = (int*)malloc(sizeof(int));
*d = i;
avlInsert(a, d);
}
avlPrintKeys(a);
avlPrintLevels(a);
for(i = 0 ; i < 40 ; i+=5)
avlRemove(a, i);
avlPrintKeys(a);
avlPrintLevels(a);
l = avlToList(a);
for(m = linkedListGetFirst(l); m != NULL ; m = m->next)
printf("%d -> ", *(int*)(m->data));
printf("\n");
linkedListDestroy(l, doNothing);
avlSetFreeFunction(a, destroyInt);
avlDestroy(a);
return 0;
}
suivant: Knapsack par recherche exhaustive
monter: Corrigés des programmes
précédent: Tas binomiaux
Table des matières
klaus
2010-08-05