J'ai un ensemble de J'ai besoin de: p>
compresser cela dans des gammes pour atteindre une représentation efficace de l'espace. Déjà mis en œuvre à l'aide d'un algorithme trivial, puisque les gammes calculées qu'une fois la vitesse n'est pas importante ici. Une fois que ce nombre de transformation des gammes résultant est généralement compris entre 5 000 et 10 000, beaucoup d'entre eux sont un seul élément, bien sûr. P> Li>
L'appartenance à tester de certains entier, des informations sur une plage spécifique dans l'ensemble n'est pas requise. Celui-ci doit être très rapide - O (1). Réfléchissait à Fonctions de hachage parfaite minimes , mais elles ne jouent pas bien avec les gammes. Bitsets est très inefficace. D'autres structures, comme des arbres binaires, ont une complexité de O (log n), la pire chose à laquelle la mise en œuvre rendait de nombreux sauts et processeurs conditionnels ne peut pas les prédire bien donner de mauvaises performances. P> LI>
ol>
Y a-t-il une structure de données ou une algorithme spécialisée dans des plages entier pour résoudre cette tâche? P> uint32 code> des entiers, il peut y avoir des millions d'articles dans l'ensemble. 50-70% d'entre eux sont consécutifs, mais dans le flux d'entrée, ils apparaissent dans une commande imprévisible. P>
7 Réponses :
Si vous savez à l'avance, quelles sont les gammes, vous pouvez alors vérifier si un entier donné est présent dans l'une des plages de O (LG N) en utilisant la stratégie décrite ci-dessous. Ce n'est pas O (1), mais il est toujours assez rapide dans la pratique. P>
L'idée de cette approche est que si vous avez fusionné toutes les gammes ensemble, vous avez une collection de gammes disjointes sur la ligne de numéro. De là, vous pouvez définir une commande sur ces intervalles en disant que l'intervalle [A, B] ≤ [C, D] iff b ≤ c. Ceci est une commande totale car toutes les gammes sont disjointes. Vous pouvez ainsi mettre tous les intervalles dans un tableau statique, puis les trier par cette commande. Cela signifie que l'intervalle le plus à gauche est dans la première fente de la matrice, et l'intervalle le plus à droite est dans la fente la plus à droite. Cette construction prend une heure (n LG n). P>
Pour vérifier si un intervalle contient un entier donné, vous pouvez effectuer une recherche binaire sur ce tableau. À partir de l'intervalle intervalle, vérifiez si l'entier est contenu dans cet intervalle. Si oui, vous avez terminé. Sinon, si la valeur est inférieure à la plus petite valeur de la plage, continuez la recherche à gauche et si la valeur est supérieure à la valeur la plus importante de la gamme, continuez la recherche à droite. C'est essentiellement une recherche binaire standard et elle devrait fonctionner dans O (LG N). P>
J'espère que cela vous aide! P>
Oui, c'est ma mise en œuvre actuelle :) Il est environ 6-7 fois plus lent que la table de hachage sur mes étuis de test, mais la table de hachage est très inefficace. Quoi qu'il en soit, +1 pour la publication;)
Vous pourrez peut-être l'optimiser un peu en vérifiant d'abord les plus grandes gammes, pour une meilleure chance de marquer un coup précoce. Peut-être faire une liste séparée de toutes les gammes avec sur un certain nombre d'éléments et faire une recherche binaire à ce sujet.
@ACTUAL: Détail de la mise en œuvre -> L'utilisation d'un arbre binaire pour construire réellement les gammes est correcte, mais une fois que les plages sont stables, vous pouvez compresser les informations dans une gamme de paires triée. La recherche binaire a la même complexité, mais elle augmente considérablement la localité de la mémoire.
@Matthieu M., Ouais, je viens de nommer la classe d'algorithmes similaires et de structures de données comme des arbres binaires. En fait, j'utilise une recherche binaire sur des tableaux.
AFAIK Il n'y a pas d'algorithme de ce type qui recherche sur la liste des entiers dans O (1). P>
On ne peut faire que O (1) recherche avec une grande quantité de mémoire. p>
Il n'est donc pas très prometteur d'essayer de trouver O (1) Algorithme de recherche sur une liste de la plage d'entier. P>
D'autre part, vous pouvez essayer une approche de Time / Memory Trape-off en examinant soigneusement votre ensemble de données (éventuellement construire une sorte de table de hachage). P>
Merci pour une idée. Je pense que je vais essayer de faire une recherche binaire sur de grandes gammes et une sorte de hachage, peut-être minimale, sur une seule-article et de petites gammes.
Eh bien, Tri de godet peut rechercher une liste dans O (1) heure. Il serait peut-être préférable de dire qu'aucun algorithme qui utilise comparaisons i> peut rechercher sur une liste entière dans O (1).
plutôt qu'un stockage / récupération de comparaison '(qui sera toujours o (log (n))), Vous devez travailler sur le stockage / récupération basé sur RADIX ». P>
En d'autres termes .. extraire des grignotants de l'UINT32 et faites une trie .. p>
Merci, je vais essayer d'essayer.
Gardez vos gammes dans une matrice triée et utilisez une recherche binaire de recherche. P>
Il est facile à mettre en œuvre, o (journal n) et utilise moins de mémoire et nécessite moins d'accès mémoire que toute autre approche à base d'arborescence, ce sera donc aussi beaucoup plus rapide. P>
Vous pouvez utiliser des arbres Y-FAST ou VAN EMDE BOASS ARBERS pour atteindre les requêtes temporelles O (LG W), où W est le nombre de bits en un mot, et vous pouvez utiliser des arbres de fusion pour obtenir une heure (LG_W N) requêtes. Le compromis optimal en termes de n est O (sqrt (lg (n))). P>
Les plus faciles à mettre en œuvre sont probablement des arbres antérieurs. Ils sont probablement plus rapides que de faire une recherche binaire, bien qu'ils nécessitent grossièrement O (LG W) = O (LG 32) = O (5) Requêtes de table de hachage, tandis que la recherche binaire nécessite grossièrement O (LG N) = O (LG 10000) = O (13) comparaisons, une recherche binaire peut être plus rapide. P>
Concernant le deuxième numéro: P>
Vous pouvez rechercher Filtres de fleurs . Les filtres de fleurs sont spécifiquement conçus pour répondre à la question de l'adhésion dans O (1), bien que la réponse soit dans le cas En outre, vous voudrez peut-être garder des gammes réelles et dégénérer des gammes (éléments simples) dans différentes structures. P>
Ceci diminue le nombre d'éléments stockés dans la matrice triée et donc la complexité de la recherche binaire effectuée là-bas. Depuis que vous déclarez que de nombreuses gammes sont dégénérées, je suppose que vous n'avez que quelques 500-1000 gammes (c'est-à-dire un ordre de grandeur inférieur) et journal (1000) ~ 10 P>
Je suggérerais donc les étapes suivantes: p>
Le test de tableau trié est effectué en premier, car à partir du numéro que vous donnez (des millions de chiffres regroupés dans un peu de milliers de gammes) si un nombre est contenu, il y a des chances que ce soit dans une plage plutôt que d'être célibataire :) p>
Une dernière note: méfiez-vous de O (1), alors qu'il peut sembler attrayant, vous n'êtes pas ici dans un cas asymptotique. À peine 5000-10000 gammes est peu nombreuses, car Log (10000) est quelque chose comme 13. Donc, ne pas pessimiser votre implémentation en obtenant une solution O (1) avec un facteur constant aussi élevé qu'il fonctionne réellement plus lentement que celui d'un O (log n ) solution :) p> n ° code> ou
peut-être code> (ce qui n'est pas aussi clair que cut en tant que oui / non : P). P>
peut-être code>, bien sûr, vous avez besoin d'un traitement ultérieur pour répondre à la question (sauf si une réponse probabiliste est suffisante dans votre cas), mais même pour que le filtre de fleurs peut agir comme une porte gardien et rejeter la plupart des interrogations pivotives. P>
Semble très pratique et prometteur. Depuis l'article Wikipedia, le filtre de floraison nécessite 4,8 bits par article, afin que nous puissions l'avoir avec environ 25% d'espace aérien. Était ma lecture droite?
Je pense que la conservation des gammes et des chiffres dans une seule structure différente pourrait être une avancée importante.
@ 9Dan: c'est un paramètre. En fonction du pourcentage de faux positif, vous souhaitez vous réaliser peut le syntoniser. Cependant, le défi ne doit généralement pas proposer M code> et
k code>, mais pour définir réellement les fonctions de hachage :)
@ 9Dan: En ce qui concerne la séparation des gammes / chiffres, je commencerais certainement à cela avant de mettre en œuvre un filtre de floraison puisqu'il s'agit d'une bête compliquée.
Dans la description de votre problème, il semble que ce qui suit pourrait être un bon compromis. Je l'ai décrit à l'aide d'une langue orientée objet, mais est facilement convertible en C à l'aide d'un type syndical ou d'une structure avec un membre de type et un pointeur. P>
Utilisez les 16 premiers bits pour indexer un tableau d'objets (de taille 65536). Dans ce tableau, il y a 5 objets possibles P>
Bien sûr, vous n'avez pas besoin de scinder à 16 bille, vous pouvez vous adapter pour refléter les statistiques de votre ensemble. En fait, vous n'avez pas besoin d'utiliser des bits consécutifs, mais il accélère le bit Twiddling, et si beaucoup de vos éléments sont consécutifs à mesure que vous prétendez donner de bonnes propriétés. P>
Espérons que cela a du sens, veuillez commenter si je dois expliquer plus pleinement. Effectivement, vous avez combiné un arbre de profondeur 2 binaires avec une gamme et un bitset pour un compromis de temps / vitesse. Si vous avez besoin de sauvegarder la mémoire, rendez-vous de l'arborescence plus profonde d'une légère augmentation correspondante de la durée de la recherche. P>
Merci, ce sera mon plan B.
Pouvez-vous être un peu plus précis sur les opérations dont vous avez besoin? D'après ce que j'ai lu, vous avez un ensemble préexistant de gammes et d'entre eux, vous souhaitez soutenir l'opération "quelle gamme, le cas échéant, contient l'entier donné?" Est-ce correct?
@TemplatetypeDef: J'ai besoin juste d'une réponse oui / non pour "ce numéro est défini?" pour un ensemble préexistant. La principale question est de savoir comment le faire dans O (1) avec des exigences d'espace pratique.
Une autre pensée - avez-vous envisagé d'utiliser quelque chose comme un diagramme de décision binaire? Je me souviens que Don Knuth a déjà parlé d'utiliser des diagrammes de décision binaire supprimés zéro pour les fonctions de codage qui sont surtout zéro (dans votre cas, vous avez une fonction de 32 bits pour savoir si le nombre est présent et la plupart du temps qu'il n'est pas possible. ). Cela vous donnerait votre heure de recherche O (1) (puisque chaque recherche prend au plus 32 étapes), même si je ne suis pas sûr de la manière dont il est respectueux de l'espace.
Un bitset serait 512 Mo. Est-ce vraiment trop d'espace? Il n'y aura pas une autre structure de données O (1).
@Markus Kull: 512 Mo sera trop car il est nécessaire de travailler avec plusieurs ensembles simultanément.