Большая О-подобная терминология, но сохраняющая постоянные - PullRequest
3 голосов
/ 04 марта 2020

Я имел дело с очень маленькими хранилищами данных, где действительно не имело значения, насколько я расточительно разбирал данные. Недавно я начал работать над хранилищем данных с записями в 100000-х годах и сейчас изучаю оптимизацию моих алгоритмов. Я просто сократил свое время в несколько сотен раз и пытался сравнить несколько других решений. У меня есть вопрос по терминологии:

Есть ли четко определенный способ, например, обозначение Big O, сказать: «Этот алгоритм занимает половину времени как этот алгоритм»?

Big O notation - это хорошо понятный кроссплатформенный способ определения временной сложности алгоритма с помощью таких вещей, как бинарный поиск по упорядоченной таблице занимает время O (log n), тогда как поиск по неупорядоченной таблице занимает O (N) время. Адриан Мейя: Большая таблица O и примеры

Запись Big O (и определение сложности времени) о темпах роста. Некоторые алгоритмы, которые принимают 2n , n и n / 2 , все растут с линейной скоростью и выражаются O(n). Таким образом, мы отбрасываем константу, предшествующую 'n', когда используем нотацию Big O, и допускаем, что она действительно полезна только для сравнения алгоритмов, которые принимают O(1), O(log n), O(n), O(n^2) и других показателей. StackOverflow: почему константа всегда отбрасывается из анализа больших О?

Лучшая причина, которую я нашел для этого, заключается в том, что эти константы зависят от реализации . Если мой компьютер WindowsXP 2002 года и ваш Windows10 компьютер 2019 года выполняют ту же задачу, WindowsXP 2n может занять время, которое ваш компьютер делает в n / 2 времени.

Часть недавно проведенных оптимизаций заключается в следующем: в моем программном обеспечении есть алгоритм, который проходит через список, скажем, 100 000 точек данных, чтобы получить максимальные и минимальные значения. Я использовал итерацию по всему списку, чтобы найти максимум, а затем итерации по всему списку, чтобы найти минимум, в двух разных функциях, которые были на расстоянии нескольких миль. Теперь я перебираю его один раз, чтобы найти максимальное и минимальное значения, а затем передаю два значения, пока они мне не понадобятся. Если мы предполагаем, что итерация по списку выполняется за n раз, тогда я использовал 2n время для итерации по списку дважды, вместо того, чтобы делать это во время n для итерации через список один раз. Неважно, какое оборудование вы используете, 18-летний компьютер или новый. Новый алгоритм выполняется в два раза быстрее.

int minValue = int.MaxValue;
int maxValue = int.MinValue;
foreach(int entry in myList)
{
    if (entry < minValue) minValue = entry;
    if (entry > maxValue) maxValue = entry;
}

(Если вы заметили, что это C# /. NET и, скажем, используйте LINQ вместо этого, чтобы ускорить алгоритм, вы явно упустили суть вопроса)

Мне не удалось найти краткий, понятный способ сказать это, как обозначение Big O. Большая О, Большая Омега, Большая Тета, маленькая нотация - все связано со сложностью времени. Таким образом, все имеют дело только с темпами роста и опускают любую константу от n.

Один из способов, о котором я подумал, состоял в том, чтобы сравнить мои две реализации алгоритма и сказать, что для 10000 точек на производственном компьютере Windows10 алгоритм A занял 15 секунд, а алгоритм B - 7,5 секунд. Но мне не нужны временные метки, просто алгоритм B работает в два раза быстрее.

Я мог бы также отказаться от записи Big O и просто сказать, что алгоритм B требует одну итерацию через данные, чтобы выполнить ту же работу, что и алгоритм A, что требует двух итераций. Это работает, но не использует понятную терминологию. Я думаю, что хорошо понятная терминология будет полезна в официальных документах, где вы пытаетесь заявить, что ваш алгоритм работает за 1/100 времени другого алгоритма. Эта потребность в терминологии заключается в том, почему, я полагаю, люди в первую очередь придумали нотацию Big O!

Итак, есть ли четко определенная терминология? Или этот вопрос глуп, и любой, кто задается вопросом, должен просто продолжить свою жизнь?

Ответы [ 3 ]

4 голосов
/ 04 марта 2020

Это можно сделать без изобретения новой записи. Например, вот как Википедия сравнивает число сравнений, выполненных восходящим heapsort с обычным heapsort (выделено мое):

В то время как обычный heapsort требует 2n log 2 n + O (n) сравнение наихудшего случая и в среднем для восходящего варианта требуется n log 2 n + O (1) сравнения в среднем и 1,5n log 2 n + O (n) в худшем случае.

То есть для больших n обычные В среднем случае heapsort выполняет вдвое больше сравнений, чем heapsort снизу вверх. Это незначительное злоупотребление нотацией , потому что оно добавляет функцию, подобную n log 2 n, к асимптотическому c термину, подобному O (1), который действительно представляет набор функции , но это понимается как "n log 2 n плюс некоторая функция в O (1)" .

В общем случае мы не Необязательно знать, каким должен быть следующий асимптотически меньший член, поэтому вместо записи 1,5n log 2 n + O (n) слабая граница 1,5n log 2 n + o ( n log n) может быть записано с использованием little o нотации .

Обратите внимание, что это имеет смысл, когда мы говорим о количестве операций (например, сравнений или перестановок), выполненных алгоритмом, но при этом Анализ c не может быть использован, чтобы дать не асимптотическую формулу c для фактического времени выполнения, потому что фактическое время выполнения все еще зависит от времени, которое требуется для выполнения основных операций c (например, чтение / запись памяти, добавление числа), поэтому время выполнения отличается от количества операций на n неизвестный постоянный коэффициент . Итак, одна из причин игнорирования постоянных факторов состоит в том, что мы можем говорить о времени выполнения, а не только о количестве операций.

1 голос
/ 04 марта 2020

Обозначения Big O, Big Omega или Big Theta помогают нам рассуждать о классах проблем и их решениях. Как только вы нашли 2 решения проблемы в одном классе, то анализ констант определенно желателен при анализе и сравнении.

Большие O-нотации также различаются для лучшего и наихудшего сценариев ios, так что дальнейшие суждения и детали определенно не рассматриваются, и неслучайно возвращение констант и других предостережений к изображению.

Поэтому, безусловно, имеет смысл говорить о O (n) решениях класса и затем сравнивать 2 * n против n алгоритмов.

0 голосов
/ 04 марта 2020

Почему бы вам не написать T2 / T1 = 2?

...