Quelle structure de données stockerait efficacement les plages entières?

10

Je dois conserver une collection d'entiers compris entre 0 et 65535 afin de pouvoir effectuer rapidement les opérations suivantes:

  • Insérer un nouvel entier
  • Insérer une plage d'entiers contigus
  • Supprimer un entier
  • Supprimer tous les entiers sous un entier
  • Tester si un entier est présent

Mes données ont la propriété de contenir souvent des séries d'entiers dans la collection. Par exemple, la collection peut à un moment donné être:

{ 121, 122, 123, 124, 3201, 3202, 5897, 8912, 8913, 8914, 18823, 18824, 40891 }

L'approche la plus simple consiste simplement à utiliser un arbre binaire équilibré comme le C ++ std :: set, cependant, en utilisant cela, je ne tire pas parti du fait que j'ai souvent des séries de nombres. Peut-être serait-il préférable de stocker une collection de gammes? Mais cela signifie qu'une plage doit pouvoir être fractionnée si un entier en son milieu est supprimé, ou jointe si l'espace entre deux plages est rempli.

Existe-t-il des structures de données existantes qui seraient bien adaptées à ce problème?

WilliamKF
la source

Réponses:

9

Je vous suggère d'utiliser un arbre de recherche binaire, augmenté afin que les feuilles puissent contenir un intervalle (une série d'entiers consécutifs). Maintenez l'invariant que les intervalles ne se chevauchent pas et sont en ordre (en suivant l'invariant de l'arbre de recherche). (Cela peut être considéré comme un cas spécial d'arbre d'intervalle ou d'arbre de segment, pour le cas spécial où les intervalles ne se chevauchent pas.)

Cette structure de données vous permet de prendre en charge toutes vos opérations en temps , où est le nombre d'intervalles. Puisque nous sommes garantis , je m'attendrais à ce que ce soit assez efficace. (En particulier, oui, vous pouvez diviser un intervalle en deux parties ou fusionner deux intervalles adjacents en un seul intervalle en temps .)n n 65535 O ( lg n )O(lgn)nn65535O(lgn)

DW
la source
5

Tout d'abord, votre question est très mal formulée, si ce n'est pour aucune autre raison, car «rapidement» ne signifie pas grand-chose. Vous devrez fournir une mesure de ce que signifie "rapide".

Au-delà de cela, lorsque vous essayez de trouver une conception pour un problème, vous devez d'abord bien comprendre le problème et poser beaucoup de questions supplémentaires . Les questions pertinentes dans ce cas semblent être (sans ordre particulier):

  • Toutes ces opérations doivent-elles être également rapides ou certaines sont-elles plus importantes que d'autres?
  • Y a-t-il d'autres considérations?
  • La mémoire est-elle une préoccupation?
  • La possibilité d'effectuer des insertions, des suppressions et des recherches à partir de plusieurs threads est-elle une préoccupation?
  • La charge de travail est-elle principalement axée sur l'insertion? Supprimer? Vous cherchez?

Deuxièmement, si votre domaine problématique est vraiment cette discussion semble tout simplement idiote. Un algorithme intelligent et sophistiqué est-il vraiment nécessaire? Surtout quand un simple tableau est une excellente option, couvrant les opérations à un seul entier en temps constant, les opérations de plage en temps linéaire et les coûts d'espace linéaire?[0,65535]

Pour un peu plus de travail, vous pourriez économiser de l'espace si cela vous inquiète, au détriment de la vitesse en stockant les données sous forme de bits dans 8192 entiers. Bien que conceptuellement, les opérations sur un seul entier soient toujours à temps constant et les opérations sur un entier à distance soient toujours à temps linéaire, elles seraient plus lentes.

Donc, si c'est vraiment votre problème, je dirais d'utiliser un tableau et de passer à d'autres choses plus importantes avec le code.

Si ce n'est pas vraiment votre problème et qu'il y a d'autres considérations que vous n'avez pas relayées (par exemple, peut-être que le domaine n'est pas vraiment et que vous essayiez de simplifier le problème que vous posiez), alors vous aurez besoin pour poser à nouveau votre question, cette fois en nous disant le problème réel .[0,65535]

Nik Bougalis
la source
3

Vous pouvez envisager une structure de données Integer telle qu'un arbre Boas de Van Emde . Une structure de données entière fonctionne sur un univers fixe . Certaines des opérations que vous avez mentionnées peuvent être mises en œuvre de manière très efficace. En particulier, l'insertion, la suppression et la demande d'un seul élément s'exécute dans . Les autres opérations (insertion / suppression en masse) peuvent être plus coûteuses, cependant, en utilisant des trucs sur l'arbre de Van Emde Boas, vous devriez pouvoir obtenir une accélération d'un facteur d'environ la taille des mots de votre système.O ( log log u )U={0,,u1}O(loglogu)

Selon la structure de vos données, il existe de nombreuses alternatives intelligentes pour stocker vos données.

A.Schulz
la source