AccueilđŸ‡«đŸ‡·Chercher

Arbre de segments

En informatique, un arbre segment (en anglais segment tree), est un arbre enracinĂ© pour stocker des intervalles ou des segments. Il permet des requĂȘtes afin de savoir quels segments contiennent un certain point. C'est, en principe, une structure statique ; c'est une structure qui ne peut plus ĂȘtre modifiĂ©e une fois qu'elle est crĂ©Ă©e. Une structure de donnĂ©es similaire est l'arbre intervalle.

Un arbre segment pour un ensemble I de n intervalles utilise un stockage de O(n log n) et peut ĂȘtre construit en un temps de O(n log n). Dans un arbre segment on peut rechercher tous les intervalles qui contiennent un certain point (la requĂȘte) en O(log n + k), oĂč k est le nombre d'intervalles ou segments extraits[1].

Les applications de l'arbre segment sont dans les domaines de la géométrie algorithmique et du systÚme d'information géographique.

L'arbre segment peut aussi ĂȘtre gĂ©nĂ©ralisĂ© Ă  des espaces avec des plus grandes dimensions.

Description de la structure

Cette section décrit la structure d'un arbre segment à 1 dimension.

Soit S l'ensemble d'intervalles, ou segments. Soit p1, p2, ..., pm la liste des points d'extrémités d'intervalle distincts, trié de gauche à droite. On considÚre le partitionnement de la réelle ligne induite par ces points. Les régions de ce partitionnement sont nommés intervalles élémentaires. Ainsi, les intervalles élémentaires, sont de gauche à droite.

Comme cela, la liste des intervalles Ă©lĂ©mentaires consistent Ă  des intervalles ouverts entre deux points d'extrĂ©mitĂ©s consĂ©cutifs pi et pi+1, alternĂ©s avec des intervalles fermĂ©s qui consistent en un seul point d'extrĂ©mitĂ©. Les points isolĂ©s sont traitĂ©s comme des intervalles car la rĂ©ponse Ă  une requĂȘte n'est pas nĂ©cessairement la mĂȘme Ă  l'intĂ©rieur d'un intervalle Ă©lĂ©mentaire et ses points d'extrĂ©mitĂ©s[2].

Exemple graphique de la structure d'un arbre segment. Cette instance est construite pour les segments montrés en bas.

Étant donnĂ© un ensemble I d'intervalles, ou segments, un arbre segment T pour I est structurĂ© comme ceci :

  • T est un arbre binaire
  • Ses feuilles correspondant aux intervalles Ă©lĂ©mentaires induits par les points d'extrĂ©mitĂ©s dans I, d'une maniĂšre ordonnĂ©e : la feuille la plus Ă  gauche correspond Ă  l'intervalle le plus Ă  gauche, ainsi de suite. L'intervalle Ă©lĂ©mentaire correspondant Ă  la feuille v est notĂ© Int(v).
  • Les nƓuds internes de T correspondent Ă  des intervalles qui sont l'union d'intervalles Ă©lĂ©mentaires : l'intervalle Int(N) correspondant au nƓud N est l'union des intervalles correspondants aux feuilles de l'arbre qui dĂ©bute Ă  la racine N. Cela implique que Int(N) est l'union des intervalles de ces deux fils (sous-arbres).
  • Chaque nƓud ou feuille v de T stocke l'intervalle Int(v) ou dans certaines structures de donnĂ©es un ensemble d'intervalles. Ce sous-ensemble canonique de nƓuds v contient les intervalles [x, xâ€Č] de I de telle maniĂšre que [x, xâ€Č] contient Int(v) et ne contient pas Int(parent(v)). Cela Ă©tant, chaque nƓud dans T stocke les segments qui couvrent son intervalle, mais qui ne couvrent pas l'intervalle de son parent[3].

Exigences de stockage

Cette section analyse le coût du stockage d'un arbre segment à 1 dimension.

Un arbre segment T sur un ensemble I de n intervalles utilise un stockage de O(n log n).

Preuve:
Lemma: Tout intervalle [x, xâ€Č] de I est stockĂ© dans l'ensemble canonique pour, au maximum, deux nƓuds Ă  la mĂȘme profondeur.
Preuve: Soit v1, v2, v3 trois nƓuds Ă  la mĂȘme profondeur, numĂ©rotĂ©s de gauche Ă  droite ; et soit p(v) le nƓud pĂšre de n'importe quel nƓud v. Supposons que [x, xâ€Č] est stockĂ© Ă  v1 and v3. Cela signifie que [x, xâ€Č] couvre en entier l'intervalle depuis le point d'extrĂ©mitĂ© gauche de Int(v1) jusqu'au point d'extrĂ©mitĂ© droite de Int(v3). Remarquons que tous les segments Ă  un niveau particulier ne se chevauchent pas et ordonnĂ©s de gauche Ă  droite : par construction, cela est vrai pour le niveau contenant les feuilles, et la propriĂ©tĂ© n'est pas perdue en allant au niveau au-dessus en combinant par pair les segments adjacents. Maintenant, soit parent(v2) = parent(v1), ou c'est celui Ă  droite de ce dernier (les arĂȘtes dans ce graphe ne se croisent pas). Dans le premier cas, le point le plus Ă  gauche de Int(parent(v2)) est le mĂȘme que le point le plus Ă  gauche de Int(v1) ; dans le second cas, le point le plus Ă  gauchede Int(parent(v2)) est Ă  droite du point le plus Ă  droite de Int(parent(v1)), et ainsi, aussi Ă  droite du point le plus Ă  droite de Int(v1). Dans les deux cas, Int(parent(v2)) dĂ©bute au niveau, ou Ă  droite, du point le plus Ă  gauche de Int(v1). Un raisonnement similaire montre que Int(parent(v2)) se termine au niveau, ou Ă  gauche, du point le plus Ă  droite de Int(v3). Int(parent(v2)) doit ainsi ĂȘtre contenu dans [x, xâ€Č] ; par consĂ©quent [x, xâ€Č] ne sera pas stockĂ© Ă  v2.
L'ensemble I a au plus 4n + 1 intervalles Ă©lĂ©mentaires. Car T est un arbre binaire Ă©quilibrĂ© avec au plus 4n + 1 feuilles, sa hauteur est O(logn). Étant donnĂ© qu'un intervalle est au plus stockĂ© deux fois Ă  une certaine profondeur de l'arbre, ainsi le stockage total est O(nlogn)[4].

Construction

Cette section décrit la construction d'un arbre segment à 1 dimension.

Un arbre segment Ă  partir de l'ensemble de segments I, peut-ĂȘtre construit comme ceci. PremiĂšrement, les points d'extrĂ©mitĂ©s des intervalles dans I sont triĂ©s. les intervalles Ă©lĂ©mentaires sont obtenus Ă  partir de cela. Ensuite, un arbre binaire Ă©quilibrĂ© est construit sur les intervalles Ă©lĂ©mentaires, et pour chaque sommet v l'intervalle Int(v) est dĂ©terminĂ©. Il reste Ă  calculer le sous-ensemble canonique pour les nƓuds. Pour rĂ©ussir cela, les intervalles dans I sont insĂ©rĂ©s un par un dans l'arbre segment. Un intervalle X = [x, xâ€Č] peut ĂȘtre insĂ©rĂ© dans un sous-arbre enracinĂ© Ă  t, en utilisant la procĂ©dure suivante[5] :

  • Si Int(T) est contenu dans X alors stocker X Ă  T, et finir.
  • Else :
  • Si X intersecte l'intervalle du fils gauche de T, alors insĂ©rer X dans ce fils, rĂ©cursivement.
  • Si X intersecte l'intervalle du fils droit de T, alors insĂ©rer X dans ce fils, rĂ©cursivement.

L'opération de construction complÚte nécessite le temps O(nlogn), n étant le nombre de segments dans I.

Preuve
Trier les points d'extrémités prend O(nlogn). Construire un arbre binaire équilibré depuis les points d'extrémités nécessite un temps linéaire en n.
L'insertion d'un intervalle X = [x, xâ€Č] dans l'arbre coĂ»te O(logn).
Preuve:Visiter chaque nƓud prend un temps constant (en assumant que les sous-ensembles canoniques sont stockĂ©s dans une structure de donnĂ©es simple, comme une liste chaĂźnĂ©e). Quand on visite un nƓud v, soit on stocke X Ă  v, ou Int(v) contient un point d'extrĂ©mitĂ© de X. Comme prouvĂ© au-dessus, un intervalle est au plus stockĂ© deux fois Ă  chaque niveau de l'arbre. Il y a aussi au plus un nƓud Ă  chaque niveau oĂč son intervalle correspondant contient x, et un nƓud oĂč son intervalle contient xâ€Č. Donc, au plus quatre nƓuds par niveau sont visitĂ©s. Étant donnĂ© qu'il y a O(logn) niveaux, le coĂ»t total de l'insertion est O(logn)[1].

RequĂȘte

Cette section dĂ©crit l'opĂ©ration d'une requĂȘte dans un arbre segment Ă  1 dimension.

Une requĂȘte pour un arbre segment, reçoit une point qx (qui devrait ĂȘtre une des feuilles de l'arbre), et retrouve une liste de tous les segments stockĂ©s qui contiennent le point qx.

Formellement Ă©noncĂ© ; en fonction d'un nƓud (sous-arbre) v et une requĂȘte sur un point qx, la requĂȘte peut ĂȘtre faite en utilisant l'algorithme suivant :

  • Signaler tous les intervalles dans I(v)
  • Si v n'est pas une feuille :
    • Si qx est dans Int(fils gauche de v) alors
      • RĂ©aliser une requĂȘte dans le fils gauche de v.
    • Si qx est dans Int(fils droit de v) alors
      • RĂ©aliser une requĂȘte dans le fils droit de v.

Si un arbre segment contient n intervalles, ceux qui contiennent un point d'une requĂȘte peuvent ĂȘtre signalĂ©s en un temps O(logn + k), oĂč k est le nombre d'intervalles signalĂ©s.

Proof:L'algorithme de requĂȘte visite un nƓud par niveau de l'arbre, donc O(logn) nƓuds au total. D'un autre cĂŽtĂ©, Ă  un nƓud v, les segments dans I sont signalĂ©s en un temps O(1 + kv), oĂč kvest le nombre d'intervalles signalĂ©s au nƓud v. La somme de tous les kv pour tous les nƓuds v visitĂ©s, est k, le nombre de segments signalĂ©s[4].

Généralisation pour de plus grandes dimensions

L'arbre segment peut ĂȘtre gĂ©nĂ©ralisĂ© pour des espaces Ă  plus grandes dimensions, dans la forme d'un arbre segment Ă  plusieurs niveaux. Les versions Ă  plus de dimensions, l'arbre segment stocke une collection d'axes-parallĂšles (hyper-)rectangles, et peut retrouver les rectangles qui contiennent le point d'une certaine requĂȘte. La structure utilise un espace de O(nlogdn) et rĂ©sout les requĂȘtes en O(logdn).

L'utilisation de cascade fractionnĂ©e diminue la borne du temps de requĂȘte par un facteur logarithmique. L'utilisation d'arbre intervalle au niveau le plus profond des structures associĂ©es diminue la borne infĂ©rieure du stockage par un facteur logarithmique[6].

Notes

Une requĂȘte qui demande tous les intervalles qui contiennent un certain point est souvent mentionnĂ© en anglais comme stabbing query[7].

L'arbre segment est moins efficace que l'arbre intervalle pour les requĂȘtes de distance dans 1 dimension, cela est dĂ» au stockage qui est davantage consĂ©quent : O(nlogn) contre O(n) pour l'arbre d'intervalle. L'importance de l'arbre segment est que les segments dans chaque nƓud, son sous-ensemble canonique peut ĂȘtre stockĂ© d'une maniĂšre arbitraire[7].

Pour n intervalles oĂč les points d'extrĂ©mitĂ©s sont dans une petite plage de nombres entiers (par exemple, dans la plage [1,...,O(n)]), une structure de donnĂ©e optimale existe avec un temps de prĂ©traitement linĂ©aire et un temps de requĂȘte de O(1+k) pour signaler tous les k intervalles qui contiennent le point d'une certaine requĂȘte.

Un autre avantage de l'arbre segment est qu'il peut ĂȘtre facilement adaptĂ© aux requĂȘtes de comptage ; qui est de signaler le nombre de segments qui contiennent un certain point, au lieu de signaler les segments eux-mĂȘmes. À la place de stocker les intervalles dans des sous-ensembles canoniques, on peut simplement stocker le nombre qu'ils sont. Ainsi un arbre linĂ©aire utilise un stockage linĂ©aire, et requiert un temps de requĂȘte de O(log n)[8].

Des versions avec de plus grandes dimensions pour l'arbre intervalle et pour les arbres de recherche prioritaies n'existent pas ; cela Ă©tant, il n'y a pas d'extension claire de ces structures qui rĂ©sout le problĂšme analogue dans des dimensions supĂ©rieurs. Mais les structures peuvent ĂȘtre utilisĂ©s comme structures associĂ©es des arbres segments[6].

Histoire

L'arbre segment a Ă©tĂ© inventĂ© par Jon Louis Bentley en 1977, dans "Solutions to Klee’s rectangle problems"[7].

Références

Sources citées

Cet article est issu de wikipedia. Text licence: CC BY-SA 4.0, Des conditions supplĂ©mentaires peuvent s’appliquer aux fichiers multimĂ©dias.