Avl.ml
De wiki-prog
Implementation des AVL
Ce module présente une implantation classique des AVL qui suit la représentation du cours d'algo. La seule particularité est l'utilisation d'une fonction (de première classe) permettant d'enregistrer les appels aux transformations d'arbres (rotation.)
(* AVL *)
(* Les clefs sont des entiers *)
type t =
Empty
| Node of int * t * int * t
(* L'arbre vide et le test du vide *)
let empty = Empty
let is_empty t = t = Empty
(* recherche d'une clef *)
let rec mem k = function
Empty -> false
| Node(k',_,_,_) when k=k' -> true
| Node(k',s,_,_) when k<k' -> mem k s
| Node(_,_,_,s) -> mem k s
(* Affichage "classique" sur la sortie standard *)
let rec print = function
Empty -> Format.printf "()"
| Node(k,fg,d,fd) ->
begin
Format.printf "@,(@[<b>%i," k;
print fg;
Format.printf ",%i," d;
print fd;
Format.printf "@])"
end
(* Affichage de l'arbre pour tikz *)
let rec print_tikz = function
Empty -> Format.printf "child {node {\ }}@,"
| Node(k,fg,d,fd) ->
begin
Format.printf "child {@[<v>node {%i,%i}@," k d;
print_tikz fg;
print_tikz fd;
Format.printf "@]}@,";
end
(* Affichage d'un arbre en LaTeX (avec tikz) à insérer dans un fichier .tex *)
let print_tex t =
begin
Format.printf "\\begin{center}\\begin{tikzpicture}";
Format.printf "[every node/.style={draw=black,circle}]@.";
begin
match t with
Empty -> Format.printf "\\node {\ };@."
| Node(k,fg,d,fd) ->
begin
Format.printf "\\node@[<v> {%i,%i}
[level/.style={level distance={max(8mm,30mm-(5mm*#1))},sibling distance=260mm/(2^#1)}] @," k d;
print_tikz fg;
print_tikz fd;
Format.printf "@];@.";
end
end;
Format.printf "\\end{tikzpicture}\\end{center}@."
end
(* Les rotations *)
(* rotation droite *)
let rd update = function
Node(k,Node(kg,fgg,deseqg,fgd),deseq,fd) ->
begin
ignore(update "rd");
Node(kg,fgg,deseqg-1,Node(k,fgd,1-deseqg,fd))
end
| _ -> assert false
(* rotation gauche *)
let rg update = function
Node(k,fg,deseq,Node(kd,fdg,deseqd,fdd)) ->
begin
ignore(update "rg");
Node(kd,Node(k,fg,-1-deseqd,fdg),1+deseqd,fdd)
end
| _ -> assert false
(* rotation gauche-droite *)
let rgd update = function
Node(k,Node(kg,fgg,dg,Node(kgd,fgdg,dgd,fgdd)),d,fd) ->
begin
let dg' =
if dgd = -1 then 1 else 0
in
let d' =
if dgd = 1 then (-1) else 0
in
ignore(update "rgd");
Node(kgd,Node(kg,fgg,dg',fgdg),0,Node(k,fgdd,d',fd))
end
| t ->
begin
print t; Format.printf "@.";
assert false
end
(* rotation droite-gauche *)
let rdg update = function
Node(k,fg,d,Node(kd,Node(kdg,fdgg,ddg,fdgd),dd,fdd)) ->
begin
let dd' =
if ddg = 1 then (-1) else 0
in
let d' =
if ddg = -1 then 1 else 0
in
ignore(update "rdg");
Node(kdg,Node(k,fg,d',fdgg),0,Node(kd,fdgd,dd',fdd))
end
| t ->
begin
print t; Format.printf "@.";
assert false
end
(* Insertion dans un AVL (fonction récursive) *)
let rec insert update k = function
Empty -> (1,Node(k,Empty,0,Empty))
| Node(k',fg,d,fd) as n when k=k' -> (0,n)
| Node(k',fg,d,fd) when k<k' ->
begin
match insert update k fg with
(0,nfg) -> (0,Node(k',nfg,d,fd))
| (_,Node(kg,fgg,dg,fgd)) ->
let (nd,n) =
let n' = Node(k',Node(kg,fgg,dg,fgd),d+1,fd) in
if d = 1 then
if dg = 1 then
match rd update n' with
Node(_,_,nd,_) as n -> (nd,n)
| _ -> assert false
else
match rgd update n' with
Node(_,_,nd,_) as n -> (nd,n)
| _ -> assert false
else
(d+1,n')
in
(nd,n)
| _ -> assert false
end
| Node(k',fg,d,fd) ->
begin
match insert update k fd with
(0,nfd) -> (0,Node(k',fg,d,nfd))
| (_,Node(kd,fdg,dd,fdd)) ->
let (nd,n) =
let n' = Node(k',fg,d-1,Node(kd,fdg,dd,fdd)) in
if d = -1 then
if dd = -1 then
match rg update n' with
Node(_,_,nd,_) as n -> (nd,n)
| _ -> assert false
else
match rdg update n' with
Node(_,_,nd,_) as n -> (nd,n)
| _ -> assert false
else
(d-1,n')
in
(nd,n)
| _ -> assert false
end
(* Insertion dans un AVL (fonction d'appel) *)
let add update k t =
match insert update k t with
(_,nt) -> nt
Cette implantation suit les algos du TD. L'affichage "LaTeX" propose une sortie en tikz/pgf (version 2) qu'il faut insérer dans un fichier LaTeX adéquat. Dans l'ensemble des fonctions précédantes, la fonction (en paramètre) update sert à enregistrer les rotations, vous pourrez voir un exemple d'utilisation dans test-arbre.ml.