Граф в Мультисете

Я давно использую C++ STL, но никогда не удосужился использовать мультимножества (или мультикарты). У меня есть вопрос, основанный на подсчете количества элементов с одинаковым ключом. Например, Вот неупорядоченный_мультисет {0, 2, 5, 1, 1, 2, 7, 5}

Если я скажу count(5), он должен вернуть 2. Есть два способа добиться этого, используя стандарты unordered_multiset C++11. 1) считать2) равный_предел, а затем вычитать полученные итераторы.

1) говорят, что занимает линейное время в количестве случаев, но 2) постоянное время. Это почему?

3 ответа

Во-первых, сложность equal_range описана по ссылке, которую вы сами предоставляете:

Average case: constant.
Worst case: linear in container size.

Во-вторых, логическая операция "вычитания результирующих итераторов" должна быть реализована с использованием линейной итерации со сложностью. O(bucket_size(bucket(key))), перебирая список или вектор хеш-значений, проверяющих совпадения, так что...

"2) equal_range and then subtracting the resulting iterator"..."is constant time"

... не является обоснованным утверждением.

Что касается "1) подсчета", его сложность также задокументирована - в этом случае:

Average case: linear in the number of elements counted.
Worst case: linear in container size.

Который опять может отличаться от вашего "линейного времени по количеству происшествий". Причина в том, что в среднем max_load_factor при значении по умолчанию 1.0 и хорошей хэш-функции будут возникать только коллизии, как при случайном рассеянии - что-то около 10-20%, так что большую часть времени единственными ключами, хэширующими для конкретного сегмента, будут те, которые вы считая - со средним постоянным кратным около 1,1x или 1,2x - следовательно, линейным.

Проблема заключается в том, что equal_range возвращает "прямой итератор" (это упомянуто в предоставленной вами ссылке), который имеет только операцию приращения, определенную в отличие от итераторов с произвольным доступом. Таким образом, чтобы вычислить разницу между двумя, мы должны увеличивать первое, пока оно не станет равным второму - это дает время линейного счета.

И, например, в стандартной библиотеке gcc счетчик реализован следующим образом:

count(const _Key& __k) const
{
  pair<const_iterator, const_iterator> __p = equal_range(__k);
  const size_type __n = std::distance(__p.first, __p.second);
  return __n;
}

1) граф

Сложность: логарифмическая по размеру и линейная по количеству совпадений

Пример: mymultiset.count(73)

Логарифмический по размеру: чтобы найти элемент в самом первом же как бинарный поиск

Линейный по количеству совпадений: поскольку элемент найден, он будет течь линейно, чтобы узнать количество совпадений, потому что, как мы знаем, наборы отсортированы

2) Равный диапазон

Это сложность: логарифмическая по размеру

"Функция возвращает пару, у которой member pair:: first является нижней границей диапазона (такой же, как lower_bound), а pair:: second является верхней границей (такой же, как upper_bound). "

Проверьте наименьшую сложность, чтобы получить верхнюю / нижнюю границу, которую вы найдете (логарифмический размер). Вы также можете проверить эту ссылку: http://www.cplusplus.com/reference/set/multiset/equal_range/

Другие вопросы по тегам