tp4.ml 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. type arbre_bin =
  2. |Vide
  3. | Noeud of int*(arbre_bin)*(arbre_bin)
  4. ;;
  5. let ex1 = Noeud(
  6. 27,
  7. Noeud(
  8. 12,
  9. Noeud(5,Vide,Vide),
  10. Noeud(
  11. 19,
  12. Noeud(17,Vide,Vide),
  13. Noeud(
  14. 24,
  15. Noeud(20,Vide,Vide),
  16. Noeud(26,Vide,Vide)
  17. )
  18. )
  19. ),
  20. Noeud(
  21. 43,
  22. Noeud(36,Vide,Vide),
  23. Noeud(77,Vide,Vide)
  24. )
  25. );;
  26. type comparaison = Inf | Egal | Sup;;
  27. let compare_int x y =
  28. if x<y then Inf else if x=y then Egal else Sup
  29. ;;
  30. let rec recherche a func x = match a with
  31. | Vide -> false
  32. | Noeud(n,g,d)->match func x n with
  33. | Inf -> recherche g func x
  34. | Egal -> true
  35. | Sup -> recherche d func x
  36. ;;
  37. (*
  38. La taille des données dans un arbre binaire de recherche est définie comme le nombre total de nœuds dans l'arbre. Chaque nœud contient une étiquette et des références vers les sous-arbres gauche et droit. Donc, la taille des données est proportionnelle au nombre de nœuds dans l'arbre.
  39. L'opération fondamentale dans l'algorithme de recherche est la comparaison entre la valeur recherchée et l'étiquette du nœud courant. Cette comparaison est réalisée en utilisant une fonction de comparaison qui détermine si la valeur est inférieure, égale ou supérieure à l'étiquette. En fonction du résultat de la comparaison, la recherche se poursuit dans le sous-arbre gauche, le sous-arbre droit ou le nœud courant est considéré comme correspondant.
  40. La complexité de l'opération fondamentale de comparaison est généralement considérée comme constante, car elle ne dépend pas de la taille des données. Dans notre cas, la fonction compare_int compare simplement deux entiers et renvoie le résultat de la comparaison. Cette opération peut être réalisée en un temps constant.
  41. Maintenant, considérons la complexité de la recherche dans l'arbre binaire de recherche. Dans le pire des cas, où l'arbre est dégénéré et prend la forme d'une liste chaînée, la hauteur de l'arbre est égale au nombre total de nœuds moins un, c'est-à-dire la taille des données moins un.
  42. Dans ce pire des cas, la recherche doit parcourir chaque nœud de l'arbre pour atteindre le nœud cible. Comme la hauteur de l'arbre est proportionnelle à la taille des données, la complexité de la recherche devient O(taille des données), ce qui est équivalent à O(h), où h est la hauteur de l'arbre.
  43. En conclusion, quelle que soit la structure de l'arbre binaire de recherche, la complexité de la recherche est O(h), où h est la hauteur de l'arbre. Cela signifie que le temps de recherche dans l'arbre est proportionnel à la hauteur de l'arbre et ne dépend pas directement de la taille totale des données dans l'arbre.
  44. *)
  45. (*a est un arbre de recherche dans tous les programmes suivants*)
  46. let rec min_gauche_max_droit arbre =
  47. match arbre with
  48. | Vide -> failwith "L'arbre est vide."
  49. | Noeud(etiquette, Vide, _) -> (etiquette, etiquette) (* Noeud le plus à gauche et le plus à droite *)
  50. | Noeud(etiquette, gauche, _) ->
  51. let (min_gauche, max_droit) = min_gauche_max_droit gauche in
  52. (min_gauche, etiquette) (* Noeud le plus à gauche de tout l'arbre, le noeud courant est le plus à droite *)
  53. ;;
  54. let rec verifie_encadre arbre x y =
  55. match arbre with
  56. | Vide -> true
  57. | Noeud(etiquette, gauche, droit) ->
  58. if x <= etiquette && etiquette <= y then
  59. verifie_encadre gauche x y && verifie_encadre droit x y
  60. else
  61. false
  62. ;;
  63. let verif_arbre_rech arbre =
  64. let (plus_a_gauche, plus_a_droite) = min_gauche_max_droit arbre in
  65. verifie_encadre arbre plus_a_gauche plus_a_droite
  66. ;;
  67. type comparaison = Inf | Egal | Sup
  68. let rec verif_tri liste func =
  69. match liste with
  70. | [] | [_] -> true (* La liste vide ou avec un seul élément est toujours triée *)
  71. | x :: y :: rest ->
  72. match func x y with
  73. | Inf -> false
  74. | _ -> verif_tri (y :: rest) func
  75. ;;
  76. let rec infixe arbre =
  77. match arbre with
  78. | Vide -> []
  79. | Noeud(etiquette, gauche, droit) -> (infixe gauche) @ [etiquette] @ (infixe droit)
  80. ;;
  81. let verif_arb_rech2 arbre func =
  82. let etiquettes = infixe arbre in
  83. verif_tri etiquettes func
  84. ;;
  85. let rec insere_feuille arbre func nouvel_element =
  86. match arbre with
  87. | Vide -> Noeud(nouvel_element, Vide, Vide) (* Place le nouvel élément sur une branche vide *)
  88. | Noeud(etiquette, gauche, droit) ->
  89. match func nouvel_element etiquette with
  90. | Inf -> Noeud(etiquette, insere_feuille gauche func nouvel_element, droit) (* Insère à gauche *)
  91. | Egal -> arbre (* L'élément est déjà présent, renvoie l'arbre inchangé *)
  92. | Sup -> Noeud(etiquette, gauche, insere_feuille droit func nouvel_element) (* Insère à droite *)
  93. ;;
  94. let insere_racine arbre func nouvel_element =
  95. match arbre with
  96. | Vide -> Noeud(nouvel_element, Vide, Vide) (* Crée un nouvel arbre avec le nouvel élément comme racine *)
  97. | Noeud(etiquette, gauche, droit) ->
  98. match func nouvel_element etiquette with
  99. | Inf -> Noeud(etiquette, insere_feuille gauche func nouvel_element, droit) (* Insère le nouvel élément à gauche de l'arbre existant *)
  100. | Egal -> arbre (* L'élément est déjà présent, renvoie l'arbre inchangé *)
  101. | Sup -> Noeud(etiquette, gauche, insere_feuille droit func nouvel_element) (* Insère le nouvel élément à droite de l'arbre existant *)
  102. ;;
  103. let rec construction_feuille liste func =
  104. match liste with
  105. | [] -> Vide (* Cas de correspondance avec une liste vide, renvoie un arbre vide *)
  106. | x :: rest -> insere_feuille (construction_feuille rest func) func x
  107. ;;
  108. let rec construction_racine liste func =
  109. match liste with
  110. | [] -> Vide (* Cas de correspondance avec une liste vide, renvoie un arbre vide *)
  111. | x :: rest -> insere_racine (construction_racine rest func) func x
  112. ;;
  113. let liste_ex1 = [1;2;3;4;5;6;7;8;9];;
  114. let liste_ex2 = [1;3;5;7;9;8;6;4;2];;
  115. let rotation_gauche arbre =
  116. match arbre with
  117. | Noeud(racine, Vide, droit) ->
  118. (match droit with
  119. | Noeud(etiquette_droit, sous_arbre_gauche, sous_arbre_droit) ->
  120. Noeud(etiquette_droit, Noeud(racine, Vide, sous_arbre_gauche), sous_arbre_droit)
  121. | _ -> arbre) (* Pas de rotation possible, renvoie l'arbre inchangé *)
  122. | _ -> arbre (* Pas de rotation possible, renvoie l'arbre inchangé *)
  123. ;;
  124. let rotation_droite arbre =
  125. match arbre with
  126. | Noeud(racine, gauche, Vide) ->
  127. (match gauche with
  128. | Noeud(etiquette_gauche, sous_arbre_gauche, sous_arbre_droit) ->
  129. Noeud(etiquette_gauche, sous_arbre_gauche, Noeud(racine, sous_arbre_droit, Vide))
  130. | _ -> arbre) (* Pas de rotation possible, renvoie l'arbre inchangé *)
  131. | _ -> arbre (* Pas de rotation possible, renvoie l'arbre inchangé *)
  132. ;;
  133. let rec mystere a1 a2 func =
  134. | _,Vide -> a1
  135. | Vide,_ -> a2
  136. | Noeud(e1,ag1,ad1), Noeud(e2, ag2,ad1) when compare e1 e2 = Inf
  137. -> mystere ad1 (Noeud(e2,mystere Noeud(e1,ag1,Vide) ag2 func, ad2)) func
  138. | Noeud(e1,ag1,ad1), Noeud(e2,ag2,ad2)
  139. -> mystere ag1 (Noeud(e2,ag2,mystere Noeud(e1,Vide,ad1) ad2 func)) func
  140. ;;
  141. (* Il s'agit d'une fonction de concatenation pour 2 arbres de recherche*)