IMHIRED Telegram 206
Так долго объяснял, что уже сам понял

Сегодня я выступил с докладом на offline-части конференции C++ Russia 2023. Тема доклада — «Что-то у меня тормозит: заглядываем внутрь стандартных контейнеров». Это доклад из рубрики «Назад к основам», поэтому он нацелен на то, чтобы осветить вещи, которые разработчикам и так должны быть известны.

Изначально я хотел собрать материалы «Алгоритмического фундамента программиста» и «Поясов по C++» и осветить особенности внутреннего устройства std::vector, std::deque и ̀std::unordered_map, которые влияют на скорость и корректность работы программы.

Однако в процессе подготовки мне пришло осознание ряда вещей, и именно им я уделил внимание в своём докладе.

Во-первых, я детально разобрал в докладе, что такое асимптотика O(1), амортизированное O(1) и O(1) в среднем. Моя центральная идея состоит в том, что «асимптотика O(1) означает, что время работы операции не зависит от размера входных данных». Такая операция может длиться сколько угодно долго. Важно только то, зависит это время от размера входных данных или нет.

Например, добавление элемента в связный список имеет асимптотику O(1), потому что оно выполняется за одно и то же время, независимо от того, сколько элементов есть в списке: ноль, десять или миллион. А вот std::vector::push_back работает за O(1), когда в нём есть свободное место, и за O(N) — когда приходится выделять буфер большего размера. То есть в общем случае это не O(1), потому что время работы зависит от количества элементов в векторе (std::vector::push_back работает за амортизированное O(1), но это уже совсем другая история).

Второй вопрос, который я разбирал в докладе, был про то, как получается, что хеш-таблица, основанная на цепочках, выполняет поиск за O(1) в среднем и O(N) в худшем случае? Что значит "в среднем" и какой случай является худшим?

Поиск в хеш-таблице работает за длину цепочки. Чем больше элементов в таблице, тем длиннее её цепочки и тем дольше будет работать поиск. А значит, время работы поиска зависит от количества элементов в хеш-таблице, а следовательно, — это не O(1). Но ведь в документации сказано, что всё-таки O(1)! Как же так получается? Всё дело в параметре load factor, который задаёт отношение количества элементов в таблице к количеству бакетов. По сути load factor определяет среднюю длину цепочек в хеш-таблице. Когда load factor становится слишком большим, в хеш-таблице выполняется рехеширование — количество бакетов увеличивается минимум вдвое, и элементы перераспределяются по ним, уменьшая load factor и среднюю длину цепочек. Таким образом, неважно, сколько элементов в нашей хеш-таблице, средняя длина цепочек в ней (а следовательно, и среднее время поиска в хеш-таблице) всегда находится в одном и том же диапазоне. То есть среднее время поиска в хеш-таблице не зависит от количества данных в ней, а значит имеет асимптотику O(1) в среднем.

Мораль этой истории в том, что я с 2000-го года связан с программированием, я был на двух финалах ACM ICPC и сделал алгоритмический курс — казалось бы, я уже ничего нового не могу открыть для себя в стандартных структурах данных. Но подготовка этого, на первый взгляд, простого доклада позволила мне достичь гораздо более глубокого понимания того, как работает структура данных, которой мы пользуемся ежедневно. Так что я и правда сам понял, пока объяснял 😉

P.S. Теперь у меня есть повод перенести эти мысли в мой «Алгоритмический фундамент программиста», сделав его ещё полезнее и проще для понимания.



tgoop.com/imhired/206
Create:
Last Update:

Так долго объяснял, что уже сам понял

Сегодня я выступил с докладом на offline-части конференции C++ Russia 2023. Тема доклада — «Что-то у меня тормозит: заглядываем внутрь стандартных контейнеров». Это доклад из рубрики «Назад к основам», поэтому он нацелен на то, чтобы осветить вещи, которые разработчикам и так должны быть известны.

Изначально я хотел собрать материалы «Алгоритмического фундамента программиста» и «Поясов по C++» и осветить особенности внутреннего устройства std::vector, std::deque и ̀std::unordered_map, которые влияют на скорость и корректность работы программы.

Однако в процессе подготовки мне пришло осознание ряда вещей, и именно им я уделил внимание в своём докладе.

Во-первых, я детально разобрал в докладе, что такое асимптотика O(1), амортизированное O(1) и O(1) в среднем. Моя центральная идея состоит в том, что «асимптотика O(1) означает, что время работы операции не зависит от размера входных данных». Такая операция может длиться сколько угодно долго. Важно только то, зависит это время от размера входных данных или нет.

Например, добавление элемента в связный список имеет асимптотику O(1), потому что оно выполняется за одно и то же время, независимо от того, сколько элементов есть в списке: ноль, десять или миллион. А вот std::vector::push_back работает за O(1), когда в нём есть свободное место, и за O(N) — когда приходится выделять буфер большего размера. То есть в общем случае это не O(1), потому что время работы зависит от количества элементов в векторе (std::vector::push_back работает за амортизированное O(1), но это уже совсем другая история).

Второй вопрос, который я разбирал в докладе, был про то, как получается, что хеш-таблица, основанная на цепочках, выполняет поиск за O(1) в среднем и O(N) в худшем случае? Что значит "в среднем" и какой случай является худшим?

Поиск в хеш-таблице работает за длину цепочки. Чем больше элементов в таблице, тем длиннее её цепочки и тем дольше будет работать поиск. А значит, время работы поиска зависит от количества элементов в хеш-таблице, а следовательно, — это не O(1). Но ведь в документации сказано, что всё-таки O(1)! Как же так получается? Всё дело в параметре load factor, который задаёт отношение количества элементов в таблице к количеству бакетов. По сути load factor определяет среднюю длину цепочек в хеш-таблице. Когда load factor становится слишком большим, в хеш-таблице выполняется рехеширование — количество бакетов увеличивается минимум вдвое, и элементы перераспределяются по ним, уменьшая load factor и среднюю длину цепочек. Таким образом, неважно, сколько элементов в нашей хеш-таблице, средняя длина цепочек в ней (а следовательно, и среднее время поиска в хеш-таблице) всегда находится в одном и том же диапазоне. То есть среднее время поиска в хеш-таблице не зависит от количества данных в ней, а значит имеет асимптотику O(1) в среднем.

Мораль этой истории в том, что я с 2000-го года связан с программированием, я был на двух финалах ACM ICPC и сделал алгоритмический курс — казалось бы, я уже ничего нового не могу открыть для себя в стандартных структурах данных. Но подготовка этого, на первый взгляд, простого доклада позволила мне достичь гораздо более глубокого понимания того, как работает структура данных, которой мы пользуемся ежедневно. Так что я и правда сам понял, пока объяснял 😉

P.S. Теперь у меня есть повод перенести эти мысли в мой «Алгоритмический фундамент программиста», сделав его ещё полезнее и проще для понимания.

BY Илья Шишков: код, собесы, IT




Share with your friend now:
tgoop.com/imhired/206

View MORE
Open in Telegram


Telegram News

Date: |

In the “Bear Market Screaming Therapy Group” on Telegram, members are only allowed to post voice notes of themselves screaming. Anything else will result in an instant ban from the group, which currently has about 75 members. With the sharp downturn in the crypto market, yelling has become a coping mechanism for many crypto traders. This screaming therapy became popular after the surge of Goblintown Ethereum NFTs at the end of May or early June. Here, holders made incoherent groaning sounds in late-night Twitter spaces. They also role-played as urine-loving Goblin creatures. So far, more than a dozen different members have contributed to the group, posting voice notes of themselves screaming, yelling, groaning, and wailing in various pitches and rhythms. The Channel name and bio must be no more than 255 characters long Done! Now you’re the proud owner of a Telegram channel. The next step is to set up and customize your channel.
from us


Telegram Илья Шишков: код, собесы, IT
FROM American