Здесь показаны различия между двумя версиями данной страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
|
basics_of_algorithms:sorting_algorithms [2023/10/03 20:28] werwolf [Пузырьковая сортировка] |
basics_of_algorithms:sorting_algorithms [2023/10/04 22:18] (текущий) werwolf [Универсальная функция сортировки] |
||
|---|---|---|---|
| Строка 48: | Строка 48: | ||
| Похожий принцип работает и с элементами массива при такой сортировке. Посмотрите на этот рисунок: | Похожий принцип работает и с элементами массива при такой сортировке. Посмотрите на этот рисунок: | ||
| - | {{ :basics_of_algorithms:image_processing20231003-26-zku720.jpg?500x600 |}} | + | {{ :basics_of_algorithms:image_processing20231003-26-zku720.png?500x700 |}} |
| + | {{ :basics_of_algorithms:bubble-sort.gif |}} | ||
| Мы идем по массиву и перемещаем вправо самый большой элемент из просмотренных. Так мы находим элемент со значением 10, который в итоге побеждает во всех сравнениях и оказывается в правом конце массива. | Мы идем по массиву и перемещаем вправо самый большой элемент из просмотренных. Так мы находим элемент со значением 10, который в итоге побеждает во всех сравнениях и оказывается в правом конце массива. | ||
| Строка 59: | Строка 59: | ||
| Пузырьковая сортировка реализуется в JavaScript с помощью такой функции: | Пузырьковая сортировка реализуется в JavaScript с помощью такой функции: | ||
| - | <code> | + | <code javascript> |
| const bubbleSort = (items) => { | const bubbleSort = (items) => { | ||
| for (let limit = items.length - 1; limit > 0; limit -= 1) { | for (let limit = items.length - 1; limit > 0; limit -= 1) { | ||
| Строка 73: | Строка 73: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def bubble_sort(items): | def bubble_sort(items): | ||
| for limit in range(len(items) - 1, 0, -1): | for limit in range(len(items) - 1, 0, -1): | ||
| Строка 82: | Строка 83: | ||
| items[i], items[i + 1] = items[i + 1], items[i] | items[i], items[i + 1] = items[i + 1], items[i] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 101: | Строка 104: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| class App { | class App { | ||
| public static void bubbleSort(int[] items) { | public static void bubbleSort(int[] items) { | ||
| Строка 119: | Строка 124: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Мы видим здесь два вложенных цикла. **Внешний цикл** ограничивает внутренний цикл на каждом проходе. Сначала он простирается до конца массива, но после первого прохода там оказывается максимальный элемент. | Мы видим здесь два вложенных цикла. **Внешний цикл** ограничивает внутренний цикл на каждом проходе. Сначала он простирается до конца массива, но после первого прохода там оказывается максимальный элемент. | ||
| Строка 124: | Строка 130: | ||
| **Внутренний цикл** на следующем проходе движется до предпоследнего элемента, а затем до пред-пред-последнего — и так до тех пор, пока не остается один элемент в левой части: | **Внутренний цикл** на следующем проходе движется до предпоследнего элемента, а затем до пред-пред-последнего — и так до тех пор, пока не остается один элемент в левой части: | ||
| - | <code> | + | <code javascript> |
| for (let limit = items.length - 1; limit > 0; limit -= 1) { | for (let limit = items.length - 1; limit > 0; limit -= 1) { | ||
| // ... | // ... | ||
| Строка 130: | Строка 136: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| for limit in range(len(items) - 1, 0, -1): | for limit in range(len(items) - 1, 0, -1): | ||
| # ... | # ... | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | ||
| - | <code> | + | <details> |
| + | <summary>PHP</summary> | ||
| + | |||
| + | <code php> | ||
| <?php | <?php | ||
| Строка 146: | Строка 156: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| for (var limit = items.length - 1; limit > 0; limit--) { | for (var limit = items.length - 1; limit > 0; limit--) { | ||
| // ... | // ... | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| + | |||
| Мы помним, что в JavaScript элементы массива нумеруются с 0 — следовательно, индекс последнего элемента массива ''items'' равен ''items.length - 1''. | Мы помним, что в JavaScript элементы массива нумеруются с 0 — следовательно, индекс последнего элемента массива ''items'' равен ''items.length - 1''. | ||
| Строка 159: | Строка 173: | ||
| Обмен двух элементов выполняется с помощью временной переменной, которую мы назвали ''temporary'' (т.е. **временная**): | Обмен двух элементов выполняется с помощью временной переменной, которую мы назвали ''temporary'' (т.е. **временная**): | ||
| - | <code> | + | <code javascript> |
| const temporary = items[i]; | const temporary = items[i]; | ||
| items[i] = items[i + 1]; | items[i] = items[i + 1]; | ||
| Строка 165: | Строка 179: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| # В Python временная переменная не требуется | # В Python временная переменная не требуется | ||
| items[i], items[i + 1] = items[i + 1], items[i] | items[i], items[i + 1] = items[i + 1], items[i] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 181: | Строка 198: | ||
| $items[$i + 1] = $temporary; | $items[$i + 1] = $temporary; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var temporary = items[i]; | var temporary = items[i]; | ||
| items[i] = items[i + 1]; | items[i] = items[i + 1]; | ||
| items[i + 1] = temporary; | items[i + 1] = temporary; | ||
| </code> | </code> | ||
| + | </details> | ||
| На каждом шаге мы находим наибольший элемент в массиве, а последний оставшийся неизбежно оказывается наименьшим — так мы получаем упорядоченный массив. Проверим работу алгоритма: | На каждом шаге мы находим наибольший элемент в массиве, а последний оставшийся неизбежно оказывается наименьшим — так мы получаем упорядоченный массив. Проверим работу алгоритма: | ||
| - | <code> | + | <code javascript> |
| const items = [2, 3, 4, 3, 1, 2, 4, 5, 1, 2]; | const items = [2, 3, 4, 3, 1, 2, 4, 5, 1, 2]; | ||
| bubbleSort(items); | bubbleSort(items); | ||
| Строка 198: | Строка 218: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| items = [2, 3, 4, 3, 1, 2, 4, 5, 1, 2] | items = [2, 3, 4, 3, 1, 2, 4, 5, 1, 2] | ||
| bubble_sort(items) | bubble_sort(items) | ||
| print(items) # => [1, 1, 2, 2, 2, 3, 3, 4, 4, 5] | print(items) # => [1, 1, 2, 2, 2, 3, 3, 4, 4, 5] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 215: | Строка 238: | ||
| print_r($items); // => [1, 1, 2, 2, 2, 3, 3, 4, 4, 5] | print_r($items); // => [1, 1, 2, 2, 2, 3, 3, 4, 4, 5] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| int[] items = {2, 3, 4, 3, 1, 2, 4, 5, 1, 2}; | int[] items = {2, 3, 4, 3, 1, 2, 4, 5, 1, 2}; | ||
| App.bubbleSort(items); | App.bubbleSort(items); | ||
| Строка 224: | Строка 249: | ||
| // => [1, 1, 2, 2, 2, 3, 3, 4, 4, 5] | // => [1, 1, 2, 2, 2, 3, 3, 4, 4, 5] | ||
| </code> | </code> | ||
| + | </details> | ||
| При пузырьковой сортировке соседние элементы часто меняются местами, поэтому она работает довольно медленно. Чтобы сэкономить время, можно сократить количество перестановок. В этом поможет **сортировка выбором**. | При пузырьковой сортировке соседние элементы часто меняются местами, поэтому она работает довольно медленно. Чтобы сэкономить время, можно сократить количество перестановок. В этом поможет **сортировка выбором**. | ||
| Строка 231: | Строка 257: | ||
| Этот алгоритм сначала проводит операции сравнения и находит наименьший элемент, а только потом помещает его в начало массива. После первого прохода алгоритм исключает первый элемент из рассмотрения и ищет минимальный элемент в оставшейся части массива, а затем помещаем его на второе место: | Этот алгоритм сначала проводит операции сравнения и находит наименьший элемент, а только потом помещает его в начало массива. После первого прохода алгоритм исключает первый элемент из рассмотрения и ищет минимальный элемент в оставшейся части массива, а затем помещаем его на второе место: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjhiNjI5NWY2YmRhNTZjZDc3YWRjYTlkMTVkYWE4YWRkLmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=30408593712626cf6e45f5428412ec61277425149f292a478ca1d7f2d85475ec|Сортировка выбором}}Этот алгоритм работает гораздо быстрее пузырьковой сортировки, потому что сравнений здесь столько же, а вот обмен всего один — в самом конце. | + | {{ :basics_of_algorithms:image_processing20231003-35-a15wqx.jpg?500X700 |}} |
| + | {{ :basics_of_algorithms:selection-sort.gif |}} | ||
| + | Этот алгоритм работает гораздо быстрее пузырьковой сортировки, потому что сравнений здесь столько же, а вот обмен всего один — в самом конце. | ||
| Рассмотрим функцию, реализующую сортировку выбором в Java Script: | Рассмотрим функцию, реализующую сортировку выбором в Java Script: | ||
| - | <code> | + | <code javascript> |
| const selectionSort = (items) => { | const selectionSort = (items) => { | ||
| for (let i = 0; i < items.length - 1; i += 1) { | for (let i = 0; i < items.length - 1; i += 1) { | ||
| Строка 252: | Строка 280: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def selection_sort(items): | def selection_sort(items): | ||
| for i in range(len(items) - 1): | for i in range(len(items) - 1): | ||
| Строка 263: | Строка 292: | ||
| items[i], items[index_min] = items[index_min], items[i] | items[i], items[index_min] = items[index_min], items[i] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 285: | Строка 316: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| class App { | class App { | ||
| public static void selectionSort(int[] items) { | public static void selectionSort(int[] items) { | ||
| Строка 306: | Строка 339: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| В реализации мы сохраняем не сам минимальный элемент, а его индекс в массиве. Это нужно потому, что в конце каждого прохода минимальный элемент записывается в начало массива. При этом элемент, который был там до этого, нужно вставить куда-то в неупорядоченную половину — легче всего просто поменять их местами. | В реализации мы сохраняем не сам минимальный элемент, а его индекс в массиве. Это нужно потому, что в конце каждого прохода минимальный элемент записывается в начало массива. При этом элемент, который был там до этого, нужно вставить куда-то в неупорядоченную половину — легче всего просто поменять их местами. | ||
| Строка 315: | Строка 349: | ||
| Возьмем для примера массив, отсортированный в порядке убывания — от больших к меньшим. Чтобы разместить элементы в порядке возрастания, надо попарно поменять их местами: первый и последний, потом второй и предпоследний, и так далее, как показано на схеме: | Возьмем для примера массив, отсортированный в порядке убывания — от больших к меньшим. Чтобы разместить элементы в порядке возрастания, надо попарно поменять их местами: первый и последний, потом второй и предпоследний, и так далее, как показано на схеме: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjJmMTg0YzUyNjJlZTQzYTk3MzY3NTdlNTVkODhjN2E0LmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=d62599f53bace5421f278065934416db311f85f3d980b5ad569e14f663b5d182|Быстрая сортировка}}Сортировки массива в обратном порядке реализуется так: | + | {{ :basics_of_algorithms:image_processing20231003-47-u6u9yi.jpg |}} |
| + | Сортировки массива в обратном порядке реализуется так: | ||
| - | <code> | + | <code javascript> |
| let left = 0; | let left = 0; | ||
| let right = items.length - 1; | let right = items.length - 1; | ||
| Строка 331: | Строка 366: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| left = 0 | left = 0 | ||
| right = len(items) - 1 | right = len(items) - 1 | ||
| Строка 342: | Строка 378: | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 360: | Строка 398: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var left = 0; | var left = 0; | ||
| var right = items.length - 1; | var right = items.length - 1; | ||
| Строка 376: | Строка 416: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| В примере выше мы создали две переменные-указателя. Переменная ''left'' указывает на следующий элемент для обмена слева, а переменная ''right'' — справа. Для обмена используем уже знакомую временную переменную ''temporary'': | В примере выше мы создали две переменные-указателя. Переменная ''left'' указывает на следующий элемент для обмена слева, а переменная ''right'' — справа. Для обмена используем уже знакомую временную переменную ''temporary'': | ||
| - | <code> | + | <code javascript> |
| const temporary = items[left]; | const temporary = items[left]; | ||
| items[left] = items[right]; | items[left] = items[right]; | ||
| Строка 385: | Строка 426: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| # В Python временная переменная не требуется | # В Python временная переменная не требуется | ||
| items[left], items[right] = items[right], items[left] | items[left], items[right] = items[right], items[left] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 401: | Строка 445: | ||
| $items[$right] = $temporary; | $items[$right] = $temporary; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var temporary = items[left]; | var temporary = items[left]; | ||
| items[left] = items[right]; | items[left] = items[right]; | ||
| items[right] = temporary; | items[right] = temporary; | ||
| </code> | </code> | ||
| + | <details> | ||
| На каждой итерации цикла после обмена мы увеличиваем левый указатель, сдвигая его вправо, и одновременно уменьшаем правый, сдвигая влево: | На каждой итерации цикла после обмена мы увеличиваем левый указатель, сдвигая его вправо, и одновременно уменьшаем правый, сдвигая влево: | ||
| - | <code> | + | <code javascript> |
| left += 1; | left += 1; | ||
| right -= 1; | right -= 1; | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| left += 1 | left += 1 | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 432: | Строка 482: | ||
| $right -= 1; | $right -= 1; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| left++; | left++; | ||
| right--; | right--; | ||
| </code> | </code> | ||
| + | </details> | ||
| Похожий подход применяется в алгоритме быстрой сортировки. Он частично упорядочивает массив, перемещая в начало маленькие элементы, а в конец — большие. | Похожий подход применяется в алгоритме быстрой сортировки. Он частично упорядочивает массив, перемещая в начало маленькие элементы, а в конец — большие. | ||
| Строка 448: | Строка 501: | ||
| Чтобы не запутаться в алгоритме быстрой сортировки, разберем его на схематичном примере. В самом начале наш массив выглядит так: | Чтобы не запутаться в алгоритме быстрой сортировки, разберем его на схематичном примере. В самом начале наш массив выглядит так: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjQ0MGVjYWM5MDQxMzVlYTk0NGU4ZDIzOWM5NDJkNjRkLmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=c39c1f76a65ab0c6c24ee97c61e48817561482ce19f0844f83f5b88a4e41ae95|Быстрая сортировка}}В качестве опорного элемента выбрано число 4. Левый указатель смотрит на 5, а правый — на 3. | + | {{ :basics_of_algorithms:image_processing20231003-24-trn55f.jpg |}} |
| + | В качестве опорного элемента выбрано число 4. Левый указатель смотрит на 5, а правый — на 3. | ||
| Далее двигаем левый указатель и пропускаем элементы меньше опорного, и ищем неправильный элемент слева. Затем двигаем правый указатель, пропуская элементы больше опорного. | Далее двигаем левый указатель и пропускаем элементы меньше опорного, и ищем неправильный элемент слева. Затем двигаем правый указатель, пропуская элементы больше опорного. | ||
| Строка 454: | Строка 508: | ||
| Таким образом мы ищем пару элементов, в которой левый больше правого. Когда пара найдена, меняем элементы местами. В нашем примере 5 и 3 находятся в неправильной позиции — их надо поменять: | Таким образом мы ищем пару элементов, в которой левый больше правого. Когда пара найдена, меняем элементы местами. В нашем примере 5 и 3 находятся в неправильной позиции — их надо поменять: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjU3YjgxNzE2NzgyNTBiNTg1NWUzNmEwNjI3MWE4NGM4LmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=4a306026587b9219e97382e05f5b63c0369e885a3c8d02cce31c0717f07a134e|Быстрая сортировка}}Ищем следующую пару для обмена. Справа от 3 находится 4 — наш следующий кандидат для обмена. Обратите внимание, что 4 — опорный элемент, но он тоже принимает участие в сравнениях и обменах. | + | {{ :basics_of_algorithms:image_processing20231003-24-y3v74i.jpg |}} |
| + | Ищем следующую пару для обмена. Справа от 3 находится 4 — наш следующий кандидат для обмена. Обратите внимание, что 4 — опорный элемент, но он тоже принимает участие в сравнениях и обменах. | ||
| Слева от числа 5 находятся числа 6, 9 и 7. Они больше опорного элемента 4, поэтому указатель их пропускает. В итоге он останавливается на числе 2: | Слева от числа 5 находятся числа 6, 9 и 7. Они больше опорного элемента 4, поэтому указатель их пропускает. В итоге он останавливается на числе 2: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjUyOWNkZjY4ODRlNWY3NWU5MjExZmE1MDZjNDU1NmFlLmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=dcb5c0f140468e718d4ea4e5e7aa1dedfa017fdd4c4b4e5d3d1991a4ab80d86e|Быстрая сортировка}}Меняем их местами и ищем следующую пару. Следующие кандидаты — числа 10 и 1: | + | {{ :basics_of_algorithms:image_processing20231003-23-6az633.jpg |}} |
| + | Меняем их местами и ищем следующую пару. Следующие кандидаты — числа 10 и 1: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6ImMxM2Q3ODk2MTU5YmU1Njk5NWMwZjk3ZjliMDBmODU0LmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=36335b58aa154e557eb5f078a740d483ad3e066bfb386950531e004a7f21e23a|Быстрая сортировка}}Меняем их местами и останавливаемся, потому что левый и правый указатели упираются друг в друга. Мы получили **частично упорядоченный массив**. Разбиваем его на две части там, где указатели встретились: | + | {{ :basics_of_algorithms:image_processing20231003-35-m8dsb6.jpg |}} |
| + | Меняем их местами и останавливаемся, потому что левый и правый указатели упираются друг в друга. Мы получили **частично упорядоченный массив**. Разбиваем его на две части там, где указатели встретились: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6ImYwODhjOGQ0ZTAwYjFhMjBlODFkYTg3MTQ1MTQzNjRjLmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=cd16a2224e8025e603665fd3247eb20e56aea9ea98b18248ed8d5041b9c11de2|Быстрая сортировка}}Продолжаем частичное упорядочивание левой и правой половин массива. Правая половина перед упорядочиванием показана на рисунке: | + | {{ :basics_of_algorithms:image_processing20231003-25-cbibo7.jpg |}} |
| + | Продолжаем частичное упорядочивание левой и правой половин массива. Правая половина перед упорядочиванием показана на рисунке: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjFkMTZhZjk1OGQ4YjlhZWFlMTc0ZDU2ZjI3NzhkYmY3LmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=434b5aa635e871cf02738b4eb4a80c38b03be7bea28fff8556bafd3d63a78e1b|Быстрая сортировка}}Выбираем новый опорный элемент из подмассива. На этот раз это 7. Сдвигая указатели, меняем местами пары 10 и 5, а также 8 и 6. Числа 4 и 9 останутся на своих местах. Частично упорядоченный подмассив принимает такой вид: | + | {{ :basics_of_algorithms:image_processing20231003-30-rxos8m.jpg |}} |
| + | Выбираем новый опорный элемент из подмассива. На этот раз это 7. Сдвигая указатели, меняем местами пары 10 и 5, а также 8 и 6. Числа 4 и 9 останутся на своих местах. Частично упорядоченный подмассив принимает такой вид: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6ImE3ZGU4NjNjM2I5ODFjODAxNmQyMTIwN2EwOTRlZWY0LmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=b438511b6c10a9baf752d108abce6e7592ee91db340680deb51792f56d8db948|Быстрая сортировка}}Левый и правый указатель встречаются посередине — на числе 7. Мы снова разбиваем массив на две половины и переходим к упорядочиванию левой и правой половин. | + | {{ :basics_of_algorithms:image_processing20231003-30-sdbdvm.jpg |}} |
| + | Левый и правый указатель встречаются посередине — на числе 7. Мы снова разбиваем массив на две половины и переходим к упорядочиванию левой и правой половин. | ||
| ==== Как реализовать быструю сортировку ==== | ==== Как реализовать быструю сортировку ==== | ||
| Строка 472: | Строка 532: | ||
| Попробуем реализовать алгоритм на JavaScript. Начнем с функции частичного упорядочивания: | Попробуем реализовать алгоритм на JavaScript. Начнем с функции частичного упорядочивания: | ||
| - | <code> | + | <code javascript> |
| const partition = (items, left, right, pivot) => { | const partition = (items, left, right, pivot) => { | ||
| while (true) { | while (true) { | ||
| Строка 497: | Строка 557: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def partition(items, left, right, pivot): | def partition(items, left, right, pivot): | ||
| while True: | while True: | ||
| Строка 515: | Строка 576: | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 545: | Строка 608: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| class App { | class App { | ||
| public static int partition(int[] items, int left, int right, int pivot) { | public static int partition(int[] items, int left, int right, int pivot) { | ||
| Строка 574: | Строка 639: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| В качестве параметров функция получает: | В качестве параметров функция получает: | ||
| Строка 583: | Строка 649: | ||
| Сначала в цикле пропускаются элементы слева, которые меньше опорного: | Сначала в цикле пропускаются элементы слева, которые меньше опорного: | ||
| - | <code> | + | <code javascript> |
| while (items[left] < pivot) { | while (items[left] < pivot) { | ||
| left += 1; | left += 1; | ||
| Строка 589: | Строка 655: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| while items[left] < pivot: | while items[left] < pivot: | ||
| left += 1 | left += 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 605: | Строка 674: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| while (items[left] < pivot) { | while (items[left] < pivot) { | ||
| left++; | left++; | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Затем пропускаются элементы справа, которые больше опорного: | Затем пропускаются элементы справа, которые больше опорного: | ||
| - | <code> | + | <code javascript> |
| while (items[right] > pivot) { | while (items[right] > pivot) { | ||
| right -= 1; | right -= 1; | ||
| Строка 622: | Строка 694: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| while items[right] > pivot: | while items[right] > pivot: | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 638: | Строка 713: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| while (items[right] > pivot) { | while (items[right] > pivot) { | ||
| right--; | right--; | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Если указатели встретились или зашли друг за друга, мы завершаем цикл и возвращаем место встречи в качестве результата. Нам предстоит разбить массив на два подмассива, поэтому надо решить, что именно возвращать. Мы можем сказать, что граница — это место, где заканчивается левый подмассив, или место, где начинается правый. Большой разницы здесь нет. | Если указатели встретились или зашли друг за друга, мы завершаем цикл и возвращаем место встречи в качестве результата. Нам предстоит разбить массив на два подмассива, поэтому надо решить, что именно возвращать. Мы можем сказать, что граница — это место, где заканчивается левый подмассив, или место, где начинается правый. Большой разницы здесь нет. | ||
| Строка 651: | Строка 729: | ||
| Решим, что функция ''partition'' возвращает индекс элемента, где начинается правый подмассив: | Решим, что функция ''partition'' возвращает индекс элемента, где начинается правый подмассив: | ||
| - | <code> | + | <code javascript> |
| if (left >= right) { | if (left >= right) { | ||
| return right + 1; | return right + 1; | ||
| Строка 657: | Строка 735: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| if left >= right: | if left >= right: | ||
| return right + 1 | return right + 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 673: | Строка 754: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| if (left >= right) { | if (left >= right) { | ||
| return right + 1; | return right + 1; | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Если указатели остановились, то они указывают на два элемента в неверном порядке. Левый указатель смотрит на элемент, который больше опорного. При этом правый указатель смотрит на элемент, который меньше опорного. | Если указатели остановились, то они указывают на два элемента в неверном порядке. Левый указатель смотрит на элемент, который больше опорного. При этом правый указатель смотрит на элемент, который меньше опорного. | ||
| Строка 686: | Строка 770: | ||
| Меняем местами и сдвигаем элементы, чтобы в следующей итерации продолжить поиск следующей неправильной пары: | Меняем местами и сдвигаем элементы, чтобы в следующей итерации продолжить поиск следующей неправильной пары: | ||
| - | <code> | + | <code java> |
| const temporary = items[left]; | const temporary = items[left]; | ||
| items[left] = items[right]; | items[left] = items[right]; | ||
| Строка 695: | Строка 779: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| items[left], items[right] = items[right], items[left] | items[left], items[right] = items[right], items[left] | ||
| left += 1 | left += 1 | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 715: | Строка 802: | ||
| $right -= 1; | $right -= 1; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var temporary = items[left]; | var temporary = items[left]; | ||
| items[left] = items[right]; | items[left] = items[right]; | ||
| items[right] = temporary; | items[right] = temporary; | ||
| </code> | </code> | ||
| + | </details> | ||
| Обычно условие завершения цикла пишут в начале (оператор ''while'') или в конце (оператор ''do…while''). В функции ''partition()'' условие становится известно в середине цикла. | Обычно условие завершения цикла пишут в начале (оператор ''while'') или в конце (оператор ''do…while''). В функции ''partition()'' условие становится известно в середине цикла. | ||
| Строка 728: | Строка 818: | ||
| В языках программирования нет специального синтаксиса для такой ситуации. Обычно программисты записывают бесконечный цикл с помощью конструкции ''while (true)'', а выход из цикла делают с помощью операторов ''break'' или ''return'': | В языках программирования нет специального синтаксиса для такой ситуации. Обычно программисты записывают бесконечный цикл с помощью конструкции ''while (true)'', а выход из цикла делают с помощью операторов ''break'' или ''return'': | ||
| - | <code> | + | <code javascript> |
| while (true) { | while (true) { | ||
| // ... | // ... | ||
| Строка 740: | Строка 830: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| <code> | <code> | ||
| Строка 751: | Строка 842: | ||
| # ... | # ... | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 767: | Строка 860: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| while (true) { | while (true) { | ||
| // ... | // ... | ||
| Строка 781: | Строка 876: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Частично упорядоченный массив нельзя назвать полностью отсортированным. Чтобы закончить сортировку, мы должны рекурсивно повторить упорядочивание для левой и правой половин массива. | Частично упорядоченный массив нельзя назвать полностью отсортированным. Чтобы закончить сортировку, мы должны рекурсивно повторить упорядочивание для левой и правой половин массива. | ||
| Строка 786: | Строка 882: | ||
| Про рекурсию мы говорили на прошлом уроке. Так выглядит рекурсивный алгоритм быстрой сортировки. Он немного похож на рекурсивную функцию бинарного поиска: | Про рекурсию мы говорили на прошлом уроке. Так выглядит рекурсивный алгоритм быстрой сортировки. Он немного похож на рекурсивную функцию бинарного поиска: | ||
| - | <code> | + | <code javascript> |
| const sort = (items, left, right) => { | const sort = (items, left, right) => { | ||
| const length = right - left + 1; | const length = right - left + 1; | ||
| Строка 802: | Строка 898: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| <code> | <code> | ||
| Строка 816: | Строка 913: | ||
| sort(items, split_index, right) | sort(items, split_index, right) | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 837: | Строка 936: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| class App { | class App { | ||
| public static int partition(int[] items, int left, int right, int pivot) { | public static int partition(int[] items, int left, int right, int pivot) { | ||
| Строка 861: | Строка 962: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Для упорядочивания нужно не менее двух элементов. Поэтому мы остановим рекурсивный вызов, когда встретим пустой подмассив или подмассив с одним элементом: | Для упорядочивания нужно не менее двух элементов. Поэтому мы остановим рекурсивный вызов, когда встретим пустой подмассив или подмассив с одним элементом: | ||
| - | <code> | + | <code javascript> |
| const length = right - left + 1; | const length = right - left + 1; | ||
| Строка 881: | Строка 983: | ||
| </code> | </code> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 892: | Строка 995: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var length = right - left + 1; | var length = right - left + 1; | ||
| Строка 902: | Строка 1007: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Функция ''partition'' возвращает индекс первого элемента в правом подмассиве. Это помогает функции ''sort'' корректно вызвать саму себя: | Функция ''partition'' возвращает индекс первого элемента в правом подмассиве. Это помогает функции ''sort'' корректно вызвать саму себя: | ||
| - | <code> | + | <code javascript> |
| const splitIndex = partition(items, left, right, pivot); | const splitIndex = partition(items, left, right, pivot); | ||
| sort(items, left, splitIndex - 1); | sort(items, left, splitIndex - 1); | ||
| Строка 911: | Строка 1017: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| split_index = partition(items, left, right, pivot) | split_index = partition(items, left, right, pivot) | ||
| sort(items, left, split_index - 1) | sort(items, left, split_index - 1) | ||
| sort(items, split_index, right) | sort(items, split_index, right) | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 928: | Строка 1037: | ||
| sort($items, $splitIndex, $right); | sort($items, $splitIndex, $right); | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var splitIndex = partition(items, left, right, pivot); | var splitIndex = partition(items, left, right, pivot); | ||
| sort(items, left, splitIndex - 1); | sort(items, left, splitIndex - 1); | ||
| sort(items, splitIndex, right); | sort(items, splitIndex, right); | ||
| </code> | </code> | ||
| + | </details> | ||
| Единственный код, который вызывает вопросы — выбор опорного элемента: | Единственный код, который вызывает вопросы — выбор опорного элемента: | ||
| - | <code> | + | <code javascript> |
| const pivot = items[left]; | const pivot = items[left]; | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| pivot = items[left] | pivot = items[left] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| $pivot = $items[$left]; | $pivot = $items[$left]; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var pivot = items[left]; | var pivot = items[left]; | ||
| </code> | </code> | ||
| + | </details> | ||
| Почему мы всегда выбираем самый левый элемент подмассива? | Почему мы всегда выбираем самый левый элемент подмассива? | ||
| Строка 975: | Строка 1093: | ||
| Чтобы упростить себе жизнь, напишем вспомогательную функцию, которая всегда сортирует массив целиком: | Чтобы упростить себе жизнь, напишем вспомогательную функцию, которая всегда сортирует массив целиком: | ||
| - | <code> | + | <code javascript> |
| const quicksort = (items) => sort(items, 0, items.length - 1); | const quicksort = (items) => sort(items, 0, items.length - 1); | ||
| Строка 983: | Строка 1101: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def quicksort(items): | def quicksort(items): | ||
| sort(items, 0, len(items) - 1) | sort(items, 0, len(items) - 1) | ||
| Строка 993: | Строка 1112: | ||
| print(items) # => [10, 24, 34, 43, 52, 55, 57, 93, 99] | print(items) # => [10, 24, 34, 43, 52, 55, 57, 93, 99] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1008: | Строка 1129: | ||
| print_r($items); // => [ 10, 24, 34, 43, 52, 55, 57, 93, 99 ] | print_r($items); // => [ 10, 24, 34, 43, 52, 55, 57, 93, 99 ] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| class App { | class App { | ||
| Строка 1026: | Строка 1149: | ||
| // => [ 10, 24, 34, 43, 52, 55, 57, 93, 99 ] | // => [ 10, 24, 34, 43, 52, 55, 57, 93, 99 ] | ||
| </code> | </code> | ||
| + | </details> | ||
| Быстрая сортировка намного эффективнее сортировки выбором. Причем эта разница особенно видна на больших массивах. Если сортировать миллион элементов, сортировка выбором окажется медленнее в десятки тысяч раз. | Быстрая сортировка намного эффективнее сортировки выбором. Причем эта разница особенно видна на больших массивах. Если сортировать миллион элементов, сортировка выбором окажется медленнее в десятки тысяч раз. | ||
| Строка 1041: | Строка 1165: | ||
| Сам массив выглядит так: | Сам массив выглядит так: | ||
| - | <code> | + | <code javascript> |
| const products = [ | const products = [ | ||
| { name: "Телевизор", price: 100000, rating: 9.1 }, | { name: "Телевизор", price: 100000, rating: 9.1 }, | ||
| Строка 1055: | Строка 1179: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| products = [ | products = [ | ||
| {"name": "Телевизор", "price": 100000, "rating": 9.1}, | {"name": "Телевизор", "price": 100000, "rating": 9.1}, | ||
| Строка 1070: | Строка 1195: | ||
| ] | ] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1088: | Строка 1215: | ||
| ]; | ]; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| Map[] products = { | Map[] products = { | ||
| Map.of ("name", "Телевизор", "price", 100000, "rating", 9.1), | Map.of ("name", "Телевизор", "price", 100000, "rating", 9.1), | ||
| Строка 1104: | Строка 1233: | ||
| }; | }; | ||
| </code> | </code> | ||
| + | </details> | ||
| Можно реализовать несколько функций сортировки, но есть и более эффективный способ. Интернет-магазину подойдет **универсальная функция сортировки**. | Можно реализовать несколько функций сортировки, но есть и более эффективный способ. Интернет-магазину подойдет **универсальная функция сортировки**. | ||
| Строка 1113: | Строка 1243: | ||
| Вот так будет выглядеть компаратор, сравнивающий элементы по цене: | Вот так будет выглядеть компаратор, сравнивающий элементы по цене: | ||
| - | <code> | + | <code javascript> |
| const compareByPrice = (item1, item2) => { | const compareByPrice = (item1, item2) => { | ||
| if (item1.price < item2.price) { | if (item1.price < item2.price) { | ||
| Строка 1125: | Строка 1255: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def compare_by_price(item1, item2): | def compare_by_price(item1, item2): | ||
| if item1[price] < item2[price]: | if item1[price] < item2[price]: | ||
| Строка 1136: | Строка 1267: | ||
| return 1 | return 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1153: | Строка 1286: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| public static ToIntBiFunction<Map<String, Object>, Map<String, Object>> compareByPrice = (item1, item2) -> { | public static ToIntBiFunction<Map<String, Object>, Map<String, Object>> compareByPrice = (item1, item2) -> { | ||
| var price1 = (int) item1.get("price"); | var price1 = (int) item1.get("price"); | ||
| Строка 1170: | Строка 1305: | ||
| }; | }; | ||
| </code> | </code> | ||
| + | </details> | ||
| А вот так — компаратор, сравнивающий элементы по рейтингу: | А вот так — компаратор, сравнивающий элементы по рейтингу: | ||
| - | <code> | + | <code javascript> |
| const compareByRating = (item1, item2) => { | const compareByRating = (item1, item2) => { | ||
| if (item1.rating < item2.rating) { | if (item1.rating < item2.rating) { | ||
| Строка 1185: | Строка 1321: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def compare_by_rating(item1, item2): | def compare_by_rating(item1, item2): | ||
| if item1[rating] < item2[rating]: | if item1[rating] < item2[rating]: | ||
| Строка 1196: | Строка 1333: | ||
| return 1 | return 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1213: | Строка 1352: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| public static ToIntBiFunction<Map<String, Object>, Map<String, Object>> compareByRating = (item1, item2) -> { | public static ToIntBiFunction<Map<String, Object>, Map<String, Object>> compareByRating = (item1, item2) -> { | ||
| var rating1 = (double) item1.get("rating"); | var rating1 = (double) item1.get("rating"); | ||
| Строка 1230: | Строка 1371: | ||
| }; | }; | ||
| </code> | </code> | ||
| + | </details> | ||
| Универсальная функция сравнивает два элемента, но не использует операторы «больше» или «меньше». Вместо этого она вызывает компаратор и проверяет результат. Так выглядит универсальная пузырьковая сортировка: | Универсальная функция сравнивает два элемента, но не использует операторы «больше» или «меньше». Вместо этого она вызывает компаратор и проверяет результат. Так выглядит универсальная пузырьковая сортировка: | ||
| - | <code> | + | <code javascript> |
| const bubbleSort = (items, comparator) => { | const bubbleSort = (items, comparator) => { | ||
| for (let limit = items.length - 1; limit > 0; limit -= 1) { | for (let limit = items.length - 1; limit > 0; limit -= 1) { | ||
| Строка 1246: | Строка 1388: | ||
| }; | }; | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| def bubble_sort(items, comparator): | def bubble_sort(items, comparator): | ||
| for limit in range(len(items) - 1, 0, -1): | for limit in range(len(items) - 1, 0, -1): | ||
| Строка 1256: | Строка 1400: | ||
| items[i], items[i + 1] = items[i + 1], items[i] | items[i], items[i + 1] = items[i + 1], items[i] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1275: | Строка 1421: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| class App { | class App { | ||
| public static void bubbleSort(Map[] items, ToIntBiFunction comparator) { | public static void bubbleSort(Map[] items, ToIntBiFunction comparator) { | ||