Next: Chapitre 5
Up: Programmes en Caml
Previous: Chapitre 3
(* {\em Ajouter à un tas, voir page \pageref{prog:ajouter-tas}} *)
type 'a tas =
{ mutable cardinal: int;
tas: 'a vect };;
let ajouter v t =
t.cardinal <- t.cardinal + 1;
let a = t.tas in
let nTas = t.cardinal in
let i = ref (nTas - 1) in
if !i >= vect_length a
then failwith "tas plein" else
while !i > 0 && a.((!i - 1) / 2) <= v do
a.(!i) <- a.((!i - 1) / 2);
i := (!i - 1) / 2
done;
a.(!i) <- v;;
let nTas = ref 0;;
let ajouter v a =
incr nTas;
let i = ref (!nTas - 1) in
while !i > 0 && a.((!i - 1) / 2) <= v do
a.(!i) <- a.((!i - 1) / 2);
i := (!i - 1) / 2
done;
a.(!i) <- v;;
(* {\em Maximum d'un tas, voir page \pageref{prog:maximum-tas}} *)
let maximum t = t.tas.(0);;
(* Supprimer dans un tas,
{\em voir page \pageref{prog:supprimer-tas}} *)
let supprimer t =
t.cardinal <- t.cardinal - 1;
let a = t.tas in
let nTas = t.cardinal in
a.(0) <- a.(nTas);
let i = ref 0
and v = a.(0)
and j = ref 0 in
begin
try
while 2 * !i + 1 < nTas do
j := 2 * !i + 1;
if !j + 1 < nTas && a.(!j + 1) > a.(!j)
then j := !j + 1;
if v >= a.(!j) then raise Exit;
a.(!i) <- a.(!j);
i := !j
done
with Exit -> ()
end;
a.(!i) <- v;;
(* {\em HeapSort, voir page \pageref{prog:heapsort}} *)
let heapsort a =
let n = vect_length a - 1 in
let t = {cardinal = 0; tas = a} in
for i = 0 to n do ajouter a.(i) t done;
for i = n downto 0 do
let v = maximum t in
supprimer t;
a.(i) <- v
done;;
let a = [| 2; 1; 2; 3; 0 |];;
heapsort a;;
#a;;
- : int vect = [|0; 1; 2; 2; 3|]
(* {\em Déclaration d'un arbre, voir page \pageref{prog:declaration-arb}} *)
(* Cas binaire *)
type 'a arbre = Vide | Noeud of 'a noeud
and 'a noeud =
{contenu: 'a; filsG: 'a arbre; filsD: 'a arbre};;
(* {\em Déclaration d'un arbre, voir page \pageref{prog:declaration2-arb}} *)
(* Cas n-aire, les fils sont
implémentés par un vecteur d'arbres. *)
type 'a arbre = Vide | Noeud of 'a noeud
and 'a noeud = {contenu: 'a; fils: 'a arbre vect};;
(* Cas n-aire, les fils sont
implémentés par une liste d'arbres. *)
type 'a arbre = Vide | Noeud of 'a noeud
and 'a noeud = {contenu: 'a; fils: 'a arbre list};;
(* {\em Ajouter dans un arbre} *)
let nouvel_arbre v a b =
Noeud {contenu = v; filsG = a; filsD = b};;
let main () =
let a5 =
nouvel_arbre 12
(nouvel_arbre 8 (nouvel_arbre 6 Vide Vide) Vide)
(nouvel_arbre 13 Vide Vide) in
nouvel_arbre 20
(nouvel_arbre 3 (nouvel_arbre 3 Vide Vide) a5)
(nouvel_arbre 25
(nouvel_arbre 21 Vide Vide)
(nouvel_arbre 28 Vide Vide));;
(* {\em Impression d'un arbre, voir page \pageref{prog:imprimer-arb}} *)
#open "printf";;
let rec imprimer a tab =
match a with
| Vide -> ()
| Noeud {contenu = c; filsG = fg; filsD = fd} ->
printf "%3d " c; imprimer fd (tab + 8);
if fg <> Vide then
printf "\n%s" (make_string tab ` `);
imprimer fg tab;;
let imprimer_arbre a =
imprimer a 0; print_newline();;
#imprimer_arbre (main ());;
20 25 28
21
3 12 13
8
6
3
- : unit = ()
(* {\em Taille d'un arbre, voir page \pageref{prog:taille-arbre}} *)
let rec taille = function
| Vide -> 0
| Noeud {filsG = fg; filsD = fd; _} ->
1 + taille fg + taille fd;;
(* {\em Arbre de recherche, voir page \pageref{prog:recherche-arb-recherche}} *)
let rec recherche v a =
match a with
| Vide -> Vide
| Noeud
{contenu = c; filsG = fg; filsD = fd} ->
if c = v then a else
if c < v then recherche v fg
else recherche v fd;;
(* Purement fonctionnel *)
let rec ajouter v = function
| Vide -> nouvel_arbre v Vide Vide
| Noeud
{contenu = c; filsG = fg; filsD = fd} ->
if v <= c
then nouvel_arbre c (ajouter v fg) fd
else nouvel_arbre c (ajouter v fd) fg;;
(* Ajout par effet mémoire *)
type 'a arbre = Vide | Noeud of 'a noeud
and 'a noeud =
{mutable contenu: 'a;
mutable filsG: 'a arbre;
mutable filsD: 'a arbre};;
let nouvel_arbre v a b =
Noeud {contenu = v; filsG = a; filsD = b};;
let rec ajouter v = function
| Vide -> nouvel_arbre v Vide Vide
| Noeud
({contenu = c; filsG = fg; filsD = fd}
as noeud) as a ->
if v <= c
then noeud.filsG <- ajouter v fg
else noeud.filsD <- ajouter v fd;
a;;
(* Exemple *)
let a1 = ajouter 1 Vide in
let a2 = ajouter 2 a1 in
let a3 = ajouter 0 a2 in
ajouter 3 a3;;
(* On ne modifie que lorsque nécessaire,
c'est-à-dire pour remplacer
un arbre vide par un arbre non vide. *)
let rec ajouter v a =
match a with
| Vide -> nouvel_arbre v Vide Vide
| Noeud
({contenu = c;
filsG = fg;
filsD = fd} as noeud) when v <= c ->
let fg' = ajouter v fg in
if fg = Vide then noeud.filsG <- fg';
a
| Noeud
({contenu = c;
filsG = fg;
filsD = fd} as noeud) ->
let fd' = ajouter v fd in
if fd = Vide then noeud.filsD <- fd';
a;;
(* {\em Ajout dans un AVL, voir page \pageref{prog:ajout-avl}} *)
type 'a avl = Vide | Noeud of 'a noeud
and 'a noeud =
{ mutable balance: int;
mutable contenu: 'a;
mutable filsG: 'a avl;
mutable filsD: 'a avl };;
#open "format";;
let rec print_avl = function
| Vide -> ()
| Noeud
{balance = bal; contenu = v;
filsG = a; filsD = b} ->
open_box 1; print_string "(";
print_int bal; print_string ": ";
print_int v; print_space();
print_avl a; print_space(); print_avl b;
print_cut(); print_string ")";
close_box();;
install_printer "print_avl";;
let nouvel_arbre bal v a b =
Noeud
{balance = bal; contenu = v;
filsG = a; filsD = b};;
let rotD = function
| Vide -> failwith "rotD"
| Noeud
({balance = bB; contenu = v;
filsG = A; filsD = c} as nB) as B ->
match A with
| Vide -> failwith "rotD"
| Noeud
({balance = bA; contenu = v;
filsG = a; filsD = b} as nA) ->
nA.filsD <- B;
nB.filsG <- b;
let bBnew = bB + 1 - min 0 bA in
let bAnew = bA + 1 + max 0 bBnew in
nA.balance <- bAnew;
nB.balance <- bBnew;
A;;
let rotG = function
| Vide -> failwith "rotG"
| Noeud
({balance = bA; contenu = v;
filsG = c; filsD = B} as nA) as A ->
match B with
| Vide -> failwith "rotG"
| Noeud
({balance = bB; contenu = v;
filsG = a; filsD = b} as nB) ->
nA.filsD <- a;
nB.filsG <- A;
let bAnew = bA - 1 - max 0 bB in
let bBnew = bB - 1 + min 0 bAnew in
nA.balance <- bAnew;
nB.balance <- bBnew;
B;;
let rec ajouter v a =
match a with
| Vide -> (nouvel_arbre 0 v Vide Vide, 1)
| Noeud
({balance = bal; contenu = c;
filsG = fg; filsD = fd} as noeud) ->
let diff =
if v <= c then
begin
let (nouvel_arbre, incr) =
ajouter v fg in
noeud.balance <-
noeud.balance - incr;
if fg = Vide
then noeud.filsG <- nouvel_arbre;
incr
end else begin
let (nouvel_arbre, incr) =
ajouter v fd in
noeud.balance <-
noeud.balance + incr;
if fd = Vide
then noeud.filsD <- nouvel_arbre;
incr
end in
if diff <> 0 && noeud.balance <> 0 then
if noeud.balance < -1 then
begin match fg with
Vide -> failwith "Vide"
| Noeud {balance = b; _} ->
if b < 0 then (rotD a, 0)
else begin
noeud.filsG <- rotG fg; (rotD a, 0)
end
end else
if noeud.balance > 1 then
begin match fd with
Vide -> failwith "Vide"
| Noeud {balance = b; _} ->
if b > 0 then (rotG a, 0)
else begin
noeud.filsD <- rotD fd; (rotG a, 0)
end
end
else (a, 1)
else (a, 0);;