0 added
0 removed
Original
2026-01-01
Modified
2026-03-10
1
<ul><li><a>Bubble Sort</a></li>
1
<ul><li><a>Bubble Sort</a></li>
2
<li><a>Merge Sort</a></li>
2
<li><a>Merge Sort</a></li>
3
<li><a>Несколько советов</a></li>
3
<li><a>Несколько советов</a></li>
4
</ul><p>При изучении алгоритмов и структур данных нередко поднимается тема<strong>сортировки</strong>элементов данных. Если говорить честно, необходимость в реализации какой-нибудь уникальной сортировки при работе со связанными структурами данных возникает довольно редко, а то и не возникает вовсе. Дело в том, что в современных языках программирования для этих целей существуют свои оптимизированные методы (тот же array.sort() в JavaScript). Так зачем же изучать данный вопрос? Дело в том, что это хороший пример как алгоритмов, так и<strong>баланса между расходом памяти и времени</strong>. В этой статье мы рассмотрим 2 самых популярных метода сортировки с разным расходованием ресурсов: Bubble Sort и Merge Sort. Для примера будем использовать язык программирования JavaScript.</p>
4
</ul><p>При изучении алгоритмов и структур данных нередко поднимается тема<strong>сортировки</strong>элементов данных. Если говорить честно, необходимость в реализации какой-нибудь уникальной сортировки при работе со связанными структурами данных возникает довольно редко, а то и не возникает вовсе. Дело в том, что в современных языках программирования для этих целей существуют свои оптимизированные методы (тот же array.sort() в JavaScript). Так зачем же изучать данный вопрос? Дело в том, что это хороший пример как алгоритмов, так и<strong>баланса между расходом памяти и времени</strong>. В этой статье мы рассмотрим 2 самых популярных метода сортировки с разным расходованием ресурсов: Bubble Sort и Merge Sort. Для примера будем использовать язык программирования JavaScript.</p>
5
<h2>Bubble Sort</h2>
5
<h2>Bubble Sort</h2>
6
<p>Идея заключается в том, чтобы, выполняя проход массиву, находить элемент с наибольшим значением, одновременно с этим "протаскивая" его в конец. Если учесть, что за одну операцию обхода мы "дотаскиваем" лишь 1 максимальный элемент, чтобы реализовать Bubble Sort, нам надо будет выполнить n-операций по обходу (здесь n - это длина массива). Таким образом, мы получаем квадратичную алгоритмическую сложность O(n^2).</p>
6
<p>Идея заключается в том, чтобы, выполняя проход массиву, находить элемент с наибольшим значением, одновременно с этим "протаскивая" его в конец. Если учесть, что за одну операцию обхода мы "дотаскиваем" лишь 1 максимальный элемент, чтобы реализовать Bubble Sort, нам надо будет выполнить n-операций по обходу (здесь n - это длина массива). Таким образом, мы получаем квадратичную алгоритмическую сложность O(n^2).</p>
7
<p>Но до того как погрузиться в реализацию, давайте сначала рассмотрим визуализацию описанного выше процесса:</p>
7
<p>Но до того как погрузиться в реализацию, давайте сначала рассмотрим визуализацию описанного выше процесса:</p>
8
<p>То есть суть работы весьма проста, и заключается она в прохождении по массиву, определении значения текущего и последнего элементов, их сравнении и распределении. Когда левый компонент больше правого, они меняются местами, после чего для сравнения берется следующий компонент. В результате мы или постоянно двигаем наибольший компонент вправо, пока он не дойдет до конца структуры данных, или, если наткнемся на компонент с бОльшим значением, перемещаемся дальше по распределенной структуре, причем последующие операции будут уже считаться связанными с новым наибольшим значением. </p>
8
<p>То есть суть работы весьма проста, и заключается она в прохождении по массиву, определении значения текущего и последнего элементов, их сравнении и распределении. Когда левый компонент больше правого, они меняются местами, после чего для сравнения берется следующий компонент. В результате мы или постоянно двигаем наибольший компонент вправо, пока он не дойдет до конца структуры данных, или, если наткнемся на компонент с бОльшим значением, перемещаемся дальше по распределенной структуре, причем последующие операции будут уже считаться связанными с новым наибольшим значением. </p>
9
<p>Теперь реализуем это в коде:</p>
9
<p>Теперь реализуем это в коде:</p>
10
<p>Может, применение Bubble Sort с ее аж квадратичной алгоритмической сложностью не так уж и практично, ведь есть и более универсальные решения, связанные с сортировкой данных? На деле все не так просто, ведь вышеописанный метод имеет одно существенное преимущество -<strong>расход памяти</strong>. Для смены мест 2-х элементов нам понадобится только одна вспомогательная переменная, в результате чего мы получаем<strong>константную сложность</strong>по памяти. А это огромный плюс, если сравнивать с<strong>сортировкой слиянием</strong>, которую мы сейчас рассмотрим.</p>
10
<p>Может, применение Bubble Sort с ее аж квадратичной алгоритмической сложностью не так уж и практично, ведь есть и более универсальные решения, связанные с сортировкой данных? На деле все не так просто, ведь вышеописанный метод имеет одно существенное преимущество -<strong>расход памяти</strong>. Для смены мест 2-х элементов нам понадобится только одна вспомогательная переменная, в результате чего мы получаем<strong>константную сложность</strong>по памяти. А это огромный плюс, если сравнивать с<strong>сортировкой слиянием</strong>, которую мы сейчас рассмотрим.</p>
11
<h2>Merge Sort</h2>
11
<h2>Merge Sort</h2>
12
<p>Вот, как она выглядит:</p>
12
<p>Вот, как она выглядит:</p>
13
<p>Глядя на гифку в первый раз, бывает сложно понять, как происходит распределение элементов. Идея тут следующая:</p>
13
<p>Глядя на гифку в первый раз, бывает сложно понять, как происходит распределение элементов. Идея тут следующая:</p>
14
<ol><li>Разбить структуру данных пополам на 2 новых массива.</li>
14
<ol><li>Разбить структуру данных пополам на 2 новых массива.</li>
15
<li>Разбить каждую половину снова пополам, потом опять пополам и так до тех пор, пока не останутся массивы, содержащие лишь 1 элемент.</li>
15
<li>Разбить каждую половину снова пополам, потом опять пополам и так до тех пор, пока не останутся массивы, содержащие лишь 1 элемент.</li>
16
<li>Выполнить операцию обратного слияния (попарно), но уже сортируя компоненты по возрастанию.</li>
16
<li>Выполнить операцию обратного слияния (попарно), но уже сортируя компоненты по возрастанию.</li>
17
</ol><p>Из-за постоянной разбивки и попарного слияния алгоритмическая сложность используемой процедуры составляет O(n * log n).</p>
17
</ol><p>Из-за постоянной разбивки и попарного слияния алгоритмическая сложность используемой процедуры составляет O(n * log n).</p>
18
<p>Смотрим на основной код:</p>
18
<p>Смотрим на основной код:</p>
19
<p>Посмотрите на картинку ниже, представляющую собой очередную визуализацию процесса, где прекрасно видно, как именно происходит разбивка и последующее обратное попарное слияние.</p>
19
<p>Посмотрите на картинку ниже, представляющую собой очередную визуализацию процесса, где прекрасно видно, как именно происходит разбивка и последующее обратное попарное слияние.</p>
20
<p>В чем же логика? Смотрите, к нам "приходят" два массива: правый и левый. Оба или уже отсортированы, или просто включают в себя лишь 1 компонент. Далее надо начинать обходить обоих (потребуется лишь один обход с 2-мя указателями: первый укажет на итерируемый компонент левого массива, второй - на компонент правого), причем брать - наименьший из 2-ух элементов, забрасывая его в новую структуру, которую мы и возвратим как отсортированную.</p>
20
<p>В чем же логика? Смотрите, к нам "приходят" два массива: правый и левый. Оба или уже отсортированы, или просто включают в себя лишь 1 компонент. Далее надо начинать обходить обоих (потребуется лишь один обход с 2-мя указателями: первый укажет на итерируемый компонент левого массива, второй - на компонент правого), причем брать - наименьший из 2-ух элементов, забрасывая его в новую структуру, которую мы и возвратим как отсортированную.</p>
21
<p>Вот наш код:</p>
21
<p>Вот наш код:</p>
22
<p>Теперь должно быть все понятно.</p>
22
<p>Теперь должно быть все понятно.</p>
23
<p>Последнее, о чем стоит сказать, - достаточно до конца пройти хотя бы один Array, потому что оставшиеся непройденные значения будут однозначно больше, в итоге их нужно будет просто добавить в конец (в коде это реализуется тоже в конце, где сливаются остатки с помощью метода<em>concat.</em>)</p>
23
<p>Последнее, о чем стоит сказать, - достаточно до конца пройти хотя бы один Array, потому что оставшиеся непройденные значения будут однозначно больше, в итоге их нужно будет просто добавить в конец (в коде это реализуется тоже в конце, где сливаются остатки с помощью метода<em>concat.</em>)</p>
24
<p>Вывод прост:<strong>более быстрая сортировка потребует существенно больше памяти</strong>. Также можно сказать еще кое-что: Bubble Sort и Merge Sort - это, по сути, одни из лучших универсальных методов сортировки. А все потому, что они стабильно работают практически в любых случаях и с любыми данными (в пределах разумного). Да, есть методы, выигрывающие по алгоритмической сложности, к примеру, Radix Sort. Но практическое использование подобных методов специфично, поэтому их вряд ли можно назвать универсальными.</p>
24
<p>Вывод прост:<strong>более быстрая сортировка потребует существенно больше памяти</strong>. Также можно сказать еще кое-что: Bubble Sort и Merge Sort - это, по сути, одни из лучших универсальных методов сортировки. А все потому, что они стабильно работают практически в любых случаях и с любыми данными (в пределах разумного). Да, есть методы, выигрывающие по алгоритмической сложности, к примеру, Radix Sort. Но практическое использование подобных методов специфично, поэтому их вряд ли можно назвать универсальными.</p>
25
<h2>Несколько советов</h2>
25
<h2>Несколько советов</h2>
26
<p><strong>Парочка полезных рекомендаций:</strong></p>
26
<p><strong>Парочка полезных рекомендаций:</strong></p>
27
<ul><li>совсем не обязательно наизусть знать все структуры данных и алгоритмы;</li>
27
<ul><li>совсем не обязательно наизусть знать все структуры данных и алгоритмы;</li>
28
<li>самые нужные в плане пользы знания, чаще всего являются наиболее простыми в плане освоения;</li>
28
<li>самые нужные в плане пользы знания, чаще всего являются наиболее простыми в плане освоения;</li>
29
<li>не надо помнить все реализации - все мы люди, поэтому какие-то реализации можно и забыть. Но на практике вам будет достаточно 1 раз в них разобраться и иметь представление об их возможностях;</li>
29
<li>не надо помнить все реализации - все мы люди, поэтому какие-то реализации можно и забыть. Но на практике вам будет достаточно 1 раз в них разобраться и иметь представление об их возможностях;</li>
30
<li>анализируйте свои алгоритмы. Надо задумываться над их эффективностью - это полезно;</li>
30
<li>анализируйте свои алгоритмы. Надо задумываться над их эффективностью - это полезно;</li>
31
<li>чем более эффективный код вам удается создавать, тем более высокую производительность и надежность будет демонстрировать ваш программный продукт (как следствие - тем более крутым разработчиком вы будете).</li>
31
<li>чем более эффективный код вам удается создавать, тем более высокую производительность и надежность будет демонстрировать ваш программный продукт (как следствие - тем более крутым разработчиком вы будете).</li>
32
</ul><p>По материалам:<a>https://dou.ua/lenta/articles/what-you-should-know-about-algorithms/</a>.</p>
32
</ul><p>По материалам:<a>https://dou.ua/lenta/articles/what-you-should-know-about-algorithms/</a>.</p>
33
<p>Какие еще статьи можно дополнительно почитать на тему структур данных:</p>
33
<p>Какие еще статьи можно дополнительно почитать на тему структур данных:</p>
34
<p>- "<a>Структуры и типы данных</a>";</p>
34
<p>- "<a>Структуры и типы данных</a>";</p>
35
<p>- "<a>Понятие структуры данных для программиста. Массивы</a>";</p>
35
<p>- "<a>Понятие структуры данных для программиста. Массивы</a>";</p>
36
<p>- "<a>Топ-8 структур данных для программиста</a>";</p>
36
<p>- "<a>Топ-8 структур данных для программиста</a>";</p>
37
<p>- "<a>Дерево как структура данных. Двоичные деревья</a>".</p>
37
<p>- "<a>Дерево как структура данных. Двоичные деревья</a>".</p>
38
<p>Изучив эти статьи, вы будете знать, что такое структуры данных, зачем они используются, как происходит распределение данных в зависимости от структуры, какие операции поддерживаются, что такое графы, деревья, боры и связные списки, какое значение имеет словосочетание first out, как обратиться к элементу в списке и т. д.</p>
38
<p>Изучив эти статьи, вы будете знать, что такое структуры данных, зачем они используются, как происходит распределение данных в зависимости от структуры, какие операции поддерживаются, что такое графы, деревья, боры и связные списки, какое значение имеет словосочетание first out, как обратиться к элементу в списке и т. д.</p>
39
<a></a>
39
<a></a>