Bon intersection d'une collection de jeux en C++

J'ai une collection de std::set. Je veux trouver l'intersection de tous les ensembles dans cette collection, le plus rapidement. Le nombre d'ensembles dans la collection est généralement très faible (~5-10), et le nombre d'éléments dans chaque jeu est est généralement de moins de 1000, mais peut parfois aller jusqu'à environ 10000. Mais j'ai besoin de faire ces intersections des dizaines de milliers de fois, aussi vite que possible. J'ai essayé de référence quelques méthodes comme suit:

  1. En place d'intersection dans un std::set objet qui, initialement, les exemplaires de la première série. Alors pour la suite des séries, on itère sur tous les élément de lui-même et l'ith ensemble de la collection, et supprime les éléments de lui-même, en tant que de besoin.
  2. À l'aide de std::set_intersection dans un temporaire std::set, swap de contenu pour un jeu actuel, puis de nouveau trouver l'intersection de l'ensemble actuel avec le jeu suivant et insérez-la dans le temp ensemble, et ainsi de suite.
  3. Manuellement itérer sur tous les éléments de toutes les séries comme dans le 1), mais à l'aide d'un vector que le conteneur de destination au lieu de std::set.
  4. Même que dans le 4, mais en utilisant une std::list au lieu d'un vector, soupçonnant un list permet d'avoir plus rapidement des suppressions dans le milieu.
  5. À l'aide de hachage de jeux (std::unordered_set) et la vérification de tous les éléments de tous les ensembles.

Comme il s'est avéré, à l'aide d'un vector est légèrement plus rapide lorsque le nombre d'éléments dans chaque set est petit, et list est légèrement plus rapide pour les grands ensembles. En place à l'aide de set est considérablement plus lent que les deux, suivie par set_intersection de hachage et de jeux. Est-il un algorithme plus rapide/discbased/astuces pour accomplir cela? Je peux poster des extraits de code si nécessaire. Merci!

La question dépend vraiment de savoir si ou non vous attendre à trouver beaucoup d'éléments communs ou non, que cela modifie le "meilleur" de la structure que l'on peut venir avec. Par exemple, un 6ème méthode pourrait être d'utiliser simplement et std::unordered_map et de compter le nombre d'occurrences de chacun des éléments. Il est O(N) dans le nombre total d'éléments. Ensuite, vous choisissez simplement les éléments qui ont un total égal au nombre de jeux, O(M) est le nombre d'éléments distincts. Aucune idée de comment il pourrait effectuer.
Je vois. Je vais opter pour cette solution, bien que je soupçonne, il ne sera pas plus rapide qu'un std::list en raison de hachage et autres frais généraux. Merci!
Cette méthode va donner le jeu en non trié. Heureusement, j'ai deux cas d'utilisation, qui nécessite le résultat dans l'ordre de tri, et une qui ne l'est pas. Si cette méthode est assez rapide, je peux l'utiliser au moins pour le cas où l'intersection n'est pas nécessaire d'être triés.
J'ai essayé cette approche, et pour mes données, ce n'était que légèrement plus vite que mon approche 5 (en utilisant unordered_set).
Vous pouvez essayer cette idée. Pire des cas linéaire (ne peut pas éviter que, si les jeux ont pour la plupart les mêmes éléments), mais si l'intersection est petit, il peut être beaucoup plus rapide.

OriginalL'auteur Paresh | 2012-10-13