Vérifier si tous les éléments d'un vecteur sont égaux en C++
Si j'ai un vecteur de valeurs et que vous souhaitez vérifier qu'ils sont tous les mêmes, quelle est la meilleure façon de le faire en C++ de manière efficace? Si je ont été de programmation dans un autre langage comme le R d'une façon mes esprits des sauts est à retourner uniquement les éléments du conteneur et puis si la longueur des éléments uniques de plus de 1, je sais que tous les éléments ne peuvent pas être les mêmes. En C++, ce qui peut être fait comme ceci:
//build an int vector
std::sort(myvector.begin(), myvector.end());
std::vector<int>::iterator it;
//Use unique algorithm to get the unique values.
it = std::unique(myvector.begin(), myvector.end());
positions.resize(std::distance(myvector.begin(),it));
if (myvector.size() > 1) {
std::cout << "All elements are not the same!" << std::endl;
}
Cependant la lecture sur internet et DONC, je vois d'autres réponses telles que l'utilisation d'un jeu ou de la find_if algorithme. Alors, quel est le moyen le plus efficace de le faire et pourquoi? J'imagine que le mien n'est pas la meilleure façon puisqu'il s'agit de tri de chaque élément, puis un redimensionnement du vecteur - mais peut-être que je me trompe.
Grâce,
Ben.
- Ceci a été demandé avant: stackoverflow.com/questions/15531258/... Les réponses à souligner, surtout, que l'efficacité dans l'O(n) comparer-tous-pour-la-première méthode peut être acquise en vous assurant de casser la boucle une fois que vous trouver le premier élément qui n'est pas égal.
- Tableau version: stackoverflow.com/questions/14120346/... est un sous-ensemble via
data()
.
Vous devez vous connecter pour publier un commentaire.
Vous n'avez pas besoin d'utiliser
std::sort
. Il peut être fait d'une manière simple:adjacent_find
, mais la mienne aurait présenté un lambda de prédicat, c'est pourquoi je n'ai pas le publier à la fin.not_equal_to
était la pièce manquante qui en fait une belle solution.vous pouvez utiliser
std::égalité
Cela permettra de comparer chaque élément avec la précédente.
Edit:
Ce qui concerne la performance, après essai avec 100 millions d'éléments, j'ai découvert que dans Visual Studio 2015
version 1
est deux fois plus rapide queversion 2
. C'est parce que le compilateur pour vs2015 utilise le jeu d'instructions sse en c++ std implémentations lorsque vous utilisez ints, float , etc..si vous utilisez _mm_testc_si128 vous permettra d'obtenir une performance similaire à
std::equal
Donné aucune contrainte sur le vecteur, vous avez à parcourir le vecteur au moins une fois, peu importe l'approche. Donc il suffit de choisir le premier élément et vérifiez que toutes les personnes sont égales.
De tri est un O(NlogN) de la tâche.
C'est facilement résoluble en temps O(N), de sorte que votre méthode actuelle est mauvaise.
Une simple O(N) serait aussi Luchian Grigore suggère, parcourir le vecteur, juste une fois, à comparer chaque élément vers le premier élément.
Alors que la complexité asymptotique de
std::unique
est linéaire, le coût réel de l'opération est probablement beaucoup plus grand que vous avez besoin, et c'est une place algorithme (il va modifier les données comme il va).La manière la plus rapide de l'approche est de supposer que si le vecteur contient un seul élément, il est unique par définition. Si le vecteur contient plus d'éléments, alors vous avez juste besoin de vérifier s'ils sont tous exactement égale à la première. Pour cela, vous avez seulement besoin de trouver le premier élément qui diffère de la première, en commençant la recherche à partir de la deuxième. Si il y a un tel élément, les éléments ne sont pas uniques.
C'est à l'aide de C++14 de la syntaxe, en C++11 de la chaîne, vous pouvez utiliser le bon type dans le lambda. En C++03, vous pouvez utiliser une combinaison de
std::not
,std::bind1st/std::bind2nd
etstd::equal
en place de la lambda.Le coût de cette approche est
distance(start,different element)
comparaisons et pas de copies. Attend et pire des cas linéaire des coûts dans le nombre de comparaisons (et pas des copies!)Dans votre cas particulier, une itération sur élément du vecteur et de trouver un élément différent du premier, serait suffisant. Vous pouvez même avoir la chance de s'arrêter avant l'évaluation de tous les éléments de votre vecteur. (Une boucle while peut être utilisé, mais j'ai ensuite collé avec une boucle for pour des raisons de lisibilité)
Dans le cas où vous voulez savoir combien de valeurs différentes de votre vecteur contient, vous pourriez construire un ensemble et vérifier sa taille afin de voir comment de nombreuses valeurs différentes sont à l'intérieur:
Vous pouvez simplement utiliser
std::count
à compter tous les éléments qui correspondent à l'élément de départ:count
a continuer, même après avoir trouvé le 1er différents élément, mais vous avez seulement besoin de savoir si il y en avait un, de sorte que ceux-ci sont purement gaspillage de cycles.vector
est très grand alors qu'il serait certainement utile d'utiliser une solution qui ne serait pas itérer sur tous les éléments.Vous pouvez utiliser FunctionalPlus(https://github.com/Dobiasd/FunctionalPlus):
Peut-être quelque chose comme ça. Il traverse vecteur, juste une fois, ne plaisante pas avec le vecteur de contenu.
Si les valeurs du vecteur sont quelque chose de différent type de base que vous avez à mettre en œuvre l'égalité de l'opérateur.
Après prise en compte de underscore_d remarques, je vais changer les solution possible
count
a continuer, même après avoir trouvé le 1er différents élément, mais vous avez seulement besoin de savoir si il y en avait un, de sorte que ceux qui sont gaspillées cycles. Je ne vois pas pourquoi nous avions besoin d'une mauvaise alternative 4 ans plus tard.par souci d'exhaustivité, car il n'est pas toujours la plus efficace, vous pouvez utiliser std::unique dans un moyen plus efficace pour décider si tous les membres sont les mêmes, mais méfiez-vous qu'après l'utilisation de std::unique cette façon, le conteneur est inutile:
Une autre approche à l'aide de
C++ 14
:qui est aussi d'ordre N.