files binomiales ; pagodes ; algorithme naïf de dessin d'arbres
Retour à la page générale de La lettre de Caml.
type arbre_binomial = Noeud of int * arbre_binomial list ;; let rec est_binomial = function | Noeud(_,[]) -> true | Noeud(a,(Noeud(b,r) as fils) :: q) -> b <= a && est_binomial fils && est_binomial (Noeud(a,q)) && list_length r = list_length q ;; type squelette_binomial = Jointure of squelette_binomial list ;; let rec squelette_binomial n = if n = 0 then Jointure([]) else match squelette_binomial (n-1) with | Jointure(fils) -> Jointure(squelette_binomial (n-1) :: fils) ;; let odd n = n mod 2 = 1 and even n = n mod 2 = 0 ;; type arbre_de_la_forêt = Rien | A of arbre_binomial and forêt_d'arbres == arbre_de_la_forêt list ;; type squelette_de_la_forêt = R | S of squelette_binomial and forêt_de_squelettes == squelette_de_la_forêt list ;; let rec forêt_de_squelettes n = let rec forêt_rec n k = if n = 0 then [ ] else (if odd n then S(squelette_binomial k) else R) :: (forêt_rec (n / 2) (k + 1)) in forêt_rec n 0 ;; let fusion_squelettes_binomiaux a b r = match a,b,r with | R,R,_ -> r,R | R,_,R -> b,R | _,R,R -> a,R | R,S(b),S(r) -> R,(match b with Jointure(fils) -> S(Jointure(r :: fils))) | S(a),R,S(r) -> R,(match a with Jointure(fils) -> S(Jointure(r :: fils))) | S(a),S(b),_ -> r,(match a with Jointure(fils) -> S(Jointure(b :: fils))) ;; let rec fusion_arbres_binomiaux a b r = match a,b,r with | Rien,Rien,_ -> r,Rien | Rien,_,Rien -> b,Rien | _,Rien,Rien -> a,Rien | Rien,_,_-> fusion_arbres_binomiaux b r a | _,Rien,_ -> fusion_arbres_binomiaux r a b | A(Noeud(a',fils_a) as arbre_a),A(Noeud(b',fils_b) as arbre_b),_ -> if b' <= a' then r,A(Noeud(a',arbre_b::fils_a)) else r,A(Noeud(b',arbre_a::fils_b)) ;; let fusion_forêts_squelettes f_a f_b = let rec fusion_rec f_a f_b r = match f_a,f_b,r with | [],[],R -> [] | [],[],_ -> [ r ] | [],_,_ -> fusion_rec [ R ] f_b r | _,[],_ -> fusion_rec f_a [ R ] r | a::qa,b::qb,r -> let s,r = fusion_squelettes_binomiaux a b r in s :: (fusion_rec qa qb r) in fusion_rec f_a f_b R ;; let fusion_forêts_binomiales f_a f_b = let rec fusion_rec f_a f_b r = match f_a,f_b,r with | [],[],Rien -> [] | [],[],_ -> [ r ] | [],_,_ -> fusion_rec [ Rien ] f_b r | _,[],_ -> fusion_rec f_a [ Rien ] r | a::qa,b::qb,r -> let s,r = fusion_arbres_binomiaux a b r in s :: (fusion_rec qa qb r) in fusion_rec f_a f_b Rien ;; let rec taille_arbre (Noeud(a,fils)) = it_list (fun x y -> x + (taille_arbre y)) 1 fils ;; let rec taille_forêt = function | [] -> 0 | Rien :: q -> taille_forêt q | A(a) :: q -> taille_forêt q + (taille_arbre a) ;; let rec do_forêt f forêt = let rec do_arbre f = function | Noeud(a,fils) -> f(a) ; do_list (do_arbre f) fils in match forêt with | [] -> () | Rien :: q -> do_forêt f q | A(a) :: q -> do_arbre f a ; do_forêt f q ;; type structure_de_forêt_binomiale = { ajout : int -> unit ; extrait_maximum : unit -> int ; vide : unit -> unit ; itère : (int -> unit) -> unit ; taille : unit -> int } ;; let crée_forêt () = let f = ref [ Rien ] in let plus_petit = fun | Rien _ -> true | _ Rien -> false | (A(Noeud(a,_))) (A(Noeud(b,_))) -> a <= b in let rec max_liste = function | [] -> failwith "Liste vide" | [ t ] -> t,[ Rien ] | t::q -> let m,q' = max_liste q in if plus_petit m t then t,(Rien :: q) else m,(t :: q') in { ajout = (function x -> f := fusion_forêts_binomiales [ A(Noeud(x,[])) ] !f ) ; vide = (function () -> f := [ Rien ]) ; taille = (function () -> taille_forêt !f) ; itère = (function phi -> do_forêt phi !f) ; extrait_maximum = (function () -> try let a,f' = max_liste !f in match a with | Rien -> failwith "Vide" | A(Noeud(a,fils)) -> let g' = map (function a -> A(a)) (rev fils) in f := fusion_forêts_binomiales f' g' ; a with _ -> failwith "Forêt vide") } ;; let tri_par_file_binomiale l = let f = crée_forêt () in do_list f.ajout l ; let résultat = ref [] in try while true do résultat := f.extrait_maximum () :: !résultat done ; !résultat with _ -> !résultat ;;
type arbre = Vide | Noeud of int * arbre * arbre ;; let est_tournoi a = let rec vérifie m = function | Vide -> true | Noeud(x,g,d) -> x <= m && vérifie x g && vérifie x d in match a with | Vide -> true | Noeud(x,g,d) -> vérifie x a ;; let rec insertion a x = match a with | Vide -> Noeud(x,Vide,Vide) | Noeud(r,_,_) when x >= r -> Noeud(x,a,Vide) | Noeud(r,g,Vide) -> Noeud(r,g,Noeud(x,Vide,Vide)) | Noeud(r,g,(Noeud(r',_,_) as d)) when r' >= x -> Noeud(r,g,insertion d x) | Noeud(r,g,d) -> Noeud(r,g,Noeud(x,d,Vide)) ;; let rec parcours = function | Vide -> [] | Noeud(r,g,d) -> (parcours g) @ [ r ] @ (parcours d) ;; let extrait_maximum = function | Vide -> failwith "arbre vide" | Noeud(m,g,d) -> m,(it_list insertion g (parcours d)) ;; let rec profil_droit = function | Vide -> -1 | Noeud(_,_,d) -> profil_droit d + 1 ;; let arbre_exemple = it_list insertion Vide [20;26;6;14;22;18;28;21;23;25;15;17] ;; type pagode = Néant | P of nud_pagode and nud_pagode = { valeur : int ; mutable bleu : pagode ; mutable rouge : pagode } ;; let crée_pagode x = let rec p = P { valeur = x ; bleu = p ; rouge = p } in p ;; let rouge (P p) = p.rouge and bleu (P p) = p.bleu and rouge_à (P p) x = p.rouge <- x and bleu_à (P p) x = p.bleu <- x and valeur (P p) = p.valeur ;; let rec pagode_d'arbre = function | Vide -> Néant | Noeud(n,g,d) -> let p = crée_pagode n in if g <> Vide then begin let pg = pagode_d'arbre g in rouge_à p (rouge pg) ; rouge_à pg p end ; if d <> Vide then begin let pd = pagode_d'arbre d in bleu_à p (bleu pd) ; bleu_à pd p end ; p ;; let pagode_exemple = pagode_d'arbre arbre_exemple ;; let rec arbre_de_pagode = function | Néant -> Vide | p -> let fils_gauche p = let rec remonte q = if rouge q = p then q else remonte (rouge q) in remonte (rouge p) and fils_droit p = let rec remonte q = if bleu q = p then q else remonte (bleu q) in remonte (bleu p) in let g = let pg = fils_gauche p in if pg = p then Vide else ( rouge_à pg (rouge p) ; let g = arbre_de_pagode pg in rouge_à pg p ; g ) and d = let pd = fils_droit p in if pd = p then Vide else ( bleu_à pd (bleu p) ; let d = arbre_de_pagode pd in bleu_à pd p ; d ) in Noeud(valeur p,g,d) ;; let fusion a b = match a,b with | Néant,b -> b | a,Néant -> a | a,b -> let rec parcours triplet = match triplet with | (_,Néant,_) -> triplet | (Néant,_,_) -> triplet | (a',b',r) -> if (valeur a') < (valeur b') then let t = bleu a' in bleu_à a' (bleu r) ; bleu_à r a' ; parcours (t,b',a') else let t = rouge b' in rouge_à b' (rouge r) ; rouge_à r b' ; parcours (a',t,b') in let a' = bleu a and b' = rouge b in bleu_à a Néant ; rouge_à b Néant ; let a',b',r = if valeur a' < valeur b' then let r = bleu a' in bleu_à a' a' ; (r,b',a') else let r = rouge b' in rouge_à b' b' ; (a',r,b') in match parcours (a',b',r) with | (a',Néant,r) -> ( bleu_à a (bleu r) ; bleu_à r a' ; a ) | (Néant,b',r) -> ( rouge_à b (rouge r) ; rouge_à r b' ; b ) ;; let insertion p x = fusion p (crée_pagode x) ;; let suppression_maximum p = let fils_gauche p = let rec remonte q = if rouge q = p then q else remonte (rouge q) in remonte (rouge p) and fils_droit p = let rec remonte q = if bleu q = p then q else remonte (bleu q) in remonte (bleu p) in let pg = fils_gauche p and pd = fils_droit p in if pg = p && pd = p then Néant else if pg = p then pd else if pd = p then pg else ( rouge_à pg (rouge p) ; bleu_à pd (bleu p) ; fusion pg pd ) ;;
type 'a arbre = Noeud of 'a * 'a arbre list ;; let exemple = Noeud(0,[ Noeud(1,[ Noeud(3,[]) ; Noeud(4,[ Noeud(7,[]) ; Noeud(8,[ Noeud(11,[]) ; Noeud(12,[]) ]) ]) ]) ; Noeud(2,[ Noeud(5,[]) ; Noeud(6,[ Noeud(9,[]) ; Noeud(10,[ Noeud(13,[]) ; Noeud(14,[]) ]) ]) ]) ]) ;; let rec mesure = function | Noeud(r,[]) -> Noeud((r,0),[]) | Noeud(r,fils) -> let fils' = map mesure fils in let largeur = it_list (fun x (Noeud((_,l),_)) -> max x l) 0 fils' in Noeud((r,largeur * (list_length fils) + (list_length fils) - 1),fils') ;; let rec place x = function | Noeud((r,largeur),[ ] ) -> Noeud((r,x),[]) | Noeud((r,largeur),[ b ]) -> Noeud((r,x),[ place x b ]) | Noeud((r,largeur),fils) -> let n = list_length fils and l = float_of_int largeur in let dx = (l +. 1.0) /. (float_of_int n) in let x1 = x -. (float_of_int (n - 1)) *. dx /. 2.0 in let rec aux x = function | [] -> [] | a :: q -> (place x a) :: (aux (x +. dx) q) in Noeud((r,x),(aux x1 fils)) ;; let x_ifie arbre = place 0.0 (mesure arbre) ;;
Retour à la page générale de La lettre de Caml.