Вы путаете сложность времени и время выполнения. См., Например, здесь .
При этом важно понимать, что такие выражения, как «постоянное время» и «не зависит от», означают, когда речь идет о сложности: в этом контексте обаиз них просто синонимы для O (1) . Таким образом, утверждение в комментарии reddit действительно верно.
В случае visit
это означает, что существует некоторая постоянная C, такая, что visit
никогда не занимает больше, чем C CPU-циклов, даже длябезумное количество типов в variant
. В частности, конечно, разрешено оставаться ниже этого числа C.
Итак, чтобы фактически ответить на ваш вопрос: использование if
- else if
цепочки исключительно обычно будет иметь линейный(то есть O (n)) сложность, как вы правильно заявили. Таким образом, если разработчик не знает, что компилятор оптимизирует его до чего-то постоянного, это недопустимо.
A switch
с большой вероятностью будет скомпилировано в таблицу переходов, которая работает в O (1),Это особенно вероятно, если case
s - это последующее число целых чисел, как здесь. Таким образом, реализация с использованием switch
должна быть законной. Однако обратите внимание, что для сложного распределения case
sa switch
будет скомпилировано как двоичный поиск, который является O (log n). См., Например, здесь .
И, наконец, учитывая то, что я сказал ранее, конечно, разрешается применять любые виды оптимизаций, если это не приводит к ухудшению алгоритмакласс сложности. Даже если это означает, что фактическое время выполнения зависит от количества типов, сложность времени не зависит.
Обновление:
На основев ваших комментариях позвольте мне привести примеры функции, по сложности , независимой от n
(иначе "константа" или O (1)), в то время как фактическое время выполнения *Конечно, 1041 * зависит от n
:
int get_max_of_first_50(std::vector<int> const& v)
{
int max = std::numeric_limits<int>::min();
for (int i = 0; i < 50; ++i)
if (v[i] > max)
max = v[i];
return max;
}
Эта функция всегда будет выполнять 50 итераций или меньше, независимо от того, насколько большим может быть v.size()
. Следовательно, по сложности, он классифицируется как константный алгоритм, независимый от n
или O (1);все три утверждения эквивалентны.
Это может выглядеть как мошенничество, и в некоторой степени я могу понять это рассуждение, но важно понимать, что именно по этой причине сложность былаВведенный таким образом в первую очередь:
- Позволяет некоторые упрощения при анализе алгоритмов. Это может легко стать очень трудным, иначе
- Забота только об огромных затратах. Обычно никого не волнует, что будет сделано за 5 или 10 мс. Но 5 дней против 10 дней имеют значение.
Кстати, этот способ "обмана" очень распространен. Другой известный пример - реализация std::sort
. В основном, большинство библиотечных реализаций, о которых я слышал, используют Quicksort (с некоторыми хитростями, поэтому это O (n log (n)) даже в худшем случае). Но для небольших последовательностей они обычно переключаются на сортировку вставкой, которая значительно быстрее в очень малых диапазонах, даже если это алгоритм со сложностью O (n ^ 2). Но, как уже объяснялось, с точки зрения сложности, это нормально, если его использование связано с константой. И с точки зрения фактического времени выполнения, это, конечно, также хорошо, так как это быстрее.