Почему Макс медленнее, чем сортировка?
я нашел это max
меньше, чем sort
функция в Python 2 и 3.
Python 2
$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 239 usec per loop
$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'max(a)'
1000 loops, best of 3: 342 usec per loop
Python 3
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 252 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a)'
1000 loops, best of 3: 371 usec per loop
почему иmax
(O(n)
) медленнее, чем (O(nlogn)
)?
3 ответа:
вы должны быть очень осторожны при использовании
timeit
модуль в Python.python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'
здесь код инициализации выполняется один раз, чтобы произвести случайный выбора
a
. Затем остальная часть кода выполняется несколько раз. В первый раз он сортирует массив, но каждый раз, когда вы вызываете метод сортировки на уже отсортированном массиве. Возвращается только самое быстрое время, поэтому вы фактически определяете, сколько времени требуется Python для сортировки уже отсортированного массива.часть Алгоритм сортировки в Python, чтобы определить, когда массив уже частично или полностью отсортированный. При полной сортировке он просто должен сканировать один раз через массив, чтобы обнаружить это, а затем он останавливается.
если вместо этого вы пытались:
python -m timeit -s 'import random;a=range(100000);random.shuffle(a)' 'sorted(a)[-1]'
затем сортировка происходит на каждом цикле синхронизации, и вы можете видеть, что время для сортировки массива действительно намного больше, чем просто найти максимальное значение.
Edit: @skyking это ответ объясняет часть я оставил необъясненной:
a.sort()
знает, что он работает над списком так может напрямую обращаться к элементам.max(a)
работает на любой произвольной итерации, поэтому должен использовать общую итерацию.
во-первых, обратите внимание, что
max()
использует протокол итератора, аlist.sort()
использует специальный код. Очевидно, что использование итератора является важным накладным расходом, поэтому вы наблюдаете эту разницу во времени.однако, кроме того, ваши тесты не являются справедливыми. Вы используете
a.sort()
в одном и том же списке несколько раз. Элемент алгоритм, используемый Python специально разработан, чтобы быть быстрым для уже (частично) отсортированных данных. Ваш тест говорят, что алгоритм делает свою работу хорошо.это честные испытания:
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a[:])' 1000 loops, best of 3: 227 usec per loop $ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a[:].sort()' 100 loops, best of 3: 2.28 msec per loop
здесь я создаю копию списка каждый раз. Как видите, порядок величины результатов разный: микро - vs миллисекунды, как и следовало ожидать.
и помните: big-Oh указывает верхнюю границу! Нижняя граница для алгоритма сортировки Python-Ω (n). Сложность O(n log n) не автоматически подразумевает, что каждый прогон занимает время, пропорциональное n log n. Это даже не означает, что он должен быть медленнее, чем о(n), но это уже другая история. Важно понимать, что в некоторых благоприятных случаях O (n log n) алгоритм может работать в O (n) времени или меньше.
это может быть потому что
l.sort
является членомlist
во времяmax
является общей функцией. Это значит, чтоl.sort
может полагаться на внутреннее представлениеlist
во времяmax
придется пройти через общий протокол итератора.это делает, что каждый элемент выборки для
l.sort
быстрее, чем каждый элемент выборки, чтоmax
делает.Я предполагаю, что если вы используете
sorted(a)
вы получите результат медленнее, чемmax(a)
.