Meilleure façon de fusionner plusieurs conteneurs STL, en supprimant les éléments en double?
J'ai deux conteneurs STL que je veux fusionner, en supprimant les éléments qui apparaissent plus d'une fois. Par exemple:
typedef std::list<int> container;
container c1;
container c2;
c1.push_back(1);
c1.push_back(2);
c1.push_back(3);
c2.push_back(2);
c2.push_back(3);
c2.push_back(4);
container c3 = unique_merge(c1, c2);
//c3 now contains the following 4 elements:
// 1, 2, 3, 4
std::unique semble être pour les éléments adjacents seulement, et dans mon cas, les conteneurs peuvent être dans n'importe quel ordre. J'ai pu faire quelques std::set ruse, je suppose:
container unique_merge(const container& c1, const container& c2)
{
std::set<container::value_type> s;
BOOST_FOREACH(const container::value_type& val, c1)
s.insert(val);
BOOST_FOREACH(const container::value_type& val, c2)
s.insert(val);
return container(s.begin(), s.end());
}
Est-il une meilleure façon ou ai-je raté quelque chose évidences?
Si vous demandez quelque chose "évidences", votre application est assez bon pour moust cas. Mais un meilleur algorithme n'existe pas, au coût de O(N * log(M)), où N est le nombre total d'éléments dans tous les contenants, et M est le nombre de conteneurs. Le code n'est pas anodin, je vais écrire plus tard, quand j'ai le temps.
Vraiment? Vous pouvez poster une réponse? ...
omg C'était en 2014...
Maintenant, je ne suis pas sûr à ce sujet. Je pense que ... , à en juger par ce que j'ai écrit, que ... peut-être ... à ce moment, j'ai pensé que chaque conteneur sont déjà triés, mais le nombre de conteneurs pourrait être un plus grand nombre (genre 1000 ou plus).
Vraiment? Vous pouvez poster une réponse? ...
omg C'était en 2014...
Maintenant, je ne suis pas sûr à ce sujet. Je pense que ... , à en juger par ce que j'ai écrit, que ... peut-être ... à ce moment, j'ai pensé que chaque conteneur sont déjà triés, mais le nombre de conteneurs pourrait être un plus grand nombre (genre 1000 ou plus).
OriginalL'auteur Rob | 2008-11-11
Vous devez vous connecter pour publier un commentaire.
Pour les listes non ordonnées, votre truc, c'est probablement l'un des meilleurs. Chaque insert doit être O(log n), avec N insère nécessaire, et la traversée sera O(n) O(N*log n).
L'autre option consiste à exécuter std::sort sur chaque liste individuellement, puis marcher à travers eux, en parallèle à l'aide de std::set_union, qui supprime les doublons pour vous. Ce sera également en O(n*log n), donc si vous êtes inquiet au sujet de la performance, vous aurez à profil. Si vous n'êtes pas, faites selon ce qui a plus de sens pour vous.
Edit:
set_union
ne fonctionnera que si il n'y a pas de doublons dans les listes initiales, sinon vous aurez à aller àsort
,merge
,unique
eterase
. Le grand O de la performance est toujours le même, avec les mêmes restrictions sur le profilage.Votre code sortes 2 const conteneurs. Qui ne fera même pas compiler.
C'est ce que je peux avoir pour pas de test pour le compiler.
OriginalL'auteur Eclipse
Vous allez avoir besoin de trier (soit explicitement, soit implicitement, par l'intermédiaire d'une triés conteneur comme jeu).
Il y a un idiome commun en utilisant std::sort/std::unique/std::erase pour obtenir des éléments uniques dans un récipient.
Afin de créer un conteneur avec le contenu de la c1, ajoutez le contenu de c2, puis trier, déplacer des éléments uniques à la fin, et de les supprimer. Quelque chose comme ceci:
OriginalL'auteur Chris Morley
Utiliser le std::set_union algorithme de la STL. Vous aurez besoin de trier votre entrée de liste d'abord-ou de créer des copies de votre entrée de listes, de les trier, puis utiliser std::set_union.
OriginalL'auteur Uhall