Pour les données triées, vous n'obtiendrez probablement pas beaucoup plus efficace que l'approche directe que vous avez tenté d'implémenter.
Je préférerais avoir quelque chose le long des lignes de cela, que je trouve plus intuitive compter vers le haut au lieu de descendre:
std::size_t count_unique_sorted(std::list<int> const& l) {
if (l.empty()) return 0;
std::size_t count = 1;
auto previous_value = l.front();
// TODO: hope that the compiler fixes that redundant first comparison...
for (auto next_value : l) {
if (next_value != previous_value) {
// the value changed! increment count and update previous_value
++count;
previous_value = next_value;
}
}
return count;
}
Vous pouvez faire l'algorithme std::unique_copy()
à compter au lieu de copier, en fournissant un OutputIterator personnalisé. Mais cela aura peu d'avantages sur le plan de la performance par rapport à l'approche présentée ci-dessus. Peut-être que cela vaudra la peine d'être revisité, quand le parallel implementations des algorithmes de C++ 17 deviendra disponible.
Voici un exemple:
template <typename T>
struct counter : public std::iterator<std::output_iterator_tag, T> {
explicit counter(std::size_t& count) : count(count) {}
counter& operator*() { return *this; }
counter& operator++() { return *this; }
void operator=(T const&) { ++count; }
private:
std::size_t& count;
};
std::size_t count_unique_sorted2(std::list<int> const& l) {
std::size_t count = 0;
std::unique_copy(l.begin(), l.end(), counter<int>(count));
return count;
}
Notez que dans les deux cas, vous voulez passer la liste comme référence const et non comme une copie dans la fonction.
Si vous pensez que cela doit encore ralentir, n'hésitez pas à explorer les joies de la parallélisation. Les avantages de cela dépendront probablement du volume et de la distribution des données. Vous devriez donc commencer un profilage systématique d'ici là.
À moins d'avoir à réordonner les valeurs, pensez à vider vos données dans un std::vector<int>
en premier lieu. Avoir un accès aléatoire itérateurs simplifie les choses et avoir une meilleure localité peut également accélérer les choses ...
'k ++'? Êtes-vous sûr de cela? – melpomene
'pour (const auto num: v)' itère la liste. Ensuite, utilisez un 'std :: map' pour le résultat et comptez le 'int' à l'index' num'. –
La liste d'entrée est-elle triée? – melpomene