Здесь показаны различия между двумя версиями данной страницы.
| Предыдущая версия справа и слева Предыдущая версия Следующая версия | Предыдущая версия | ||
|
basics_of_algorithms:sorting_algorithms [2023/10/04 21:36] werwolf [Быстрая сортировка] |
basics_of_algorithms:sorting_algorithms [2023/10/04 22:18] (текущий) werwolf [Универсальная функция сортировки] |
||
|---|---|---|---|
| Строка 48: | Строка 48: | ||
| Похожий принцип работает и с элементами массива при такой сортировке. Посмотрите на этот рисунок: | Похожий принцип работает и с элементами массива при такой сортировке. Посмотрите на этот рисунок: | ||
| - | {{ :basics_of_algorithms:image_processing20231003-26-zku720.jpg?500x700 |}} | + | {{ :basics_of_algorithms:image_processing20231003-26-zku720.png?500x700 |}} |
| {{ :basics_of_algorithms:bubble-sort.gif |}} | {{ :basics_of_algorithms:bubble-sort.gif |}} | ||
| Строка 257: | Строка 257: | ||
| Этот алгоритм сначала проводит операции сравнения и находит наименьший элемент, а только потом помещает его в начало массива. После первого прохода алгоритм исключает первый элемент из рассмотрения и ищет минимальный элемент в оставшейся части массива, а затем помещаем его на второе место: | Этот алгоритм сначала проводит операции сравнения и находит наименьший элемент, а только потом помещает его в начало массива. После первого прохода алгоритм исключает первый элемент из рассмотрения и ищет минимальный элемент в оставшейся части массива, а затем помещаем его на второе место: | ||
| + | {{ :basics_of_algorithms:image_processing20231003-35-a15wqx.jpg?500X700 |}} | ||
| {{ :basics_of_algorithms:selection-sort.gif |}} | {{ :basics_of_algorithms:selection-sort.gif |}} | ||
| Этот алгоритм работает гораздо быстрее пузырьковой сортировки, потому что сравнений здесь столько же, а вот обмен всего один — в самом конце. | Этот алгоритм работает гораздо быстрее пузырьковой сортировки, потому что сравнений здесь столько же, а вот обмен всего один — в самом конце. | ||
| Строка 349: | Строка 349: | ||
| Возьмем для примера массив, отсортированный в порядке убывания — от больших к меньшим. Чтобы разместить элементы в порядке возрастания, надо попарно поменять их местами: первый и последний, потом второй и предпоследний, и так далее, как показано на схеме: | Возьмем для примера массив, отсортированный в порядке убывания — от больших к меньшим. Чтобы разместить элементы в порядке возрастания, надо попарно поменять их местами: первый и последний, потом второй и предпоследний, и так далее, как показано на схеме: | ||
| - | {{https://cdn2.hexlet.io/derivations/image/original/eyJpZCI6IjJmMTg0YzUyNjJlZTQzYTk3MzY3NTdlNTVkODhjN2E0LmpwZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=d62599f53bace5421f278065934416db311f85f3d980b5ad569e14f663b5d182|Быстрая сортировка}}Сортировки массива в обратном порядке реализуется так: | + | {{ :basics_of_algorithms:image_processing20231003-47-u6u9yi.jpg |}} |
| + | Сортировки массива в обратном порядке реализуется так: | ||
| <code javascript> | <code javascript> | ||
| Строка 365: | Строка 366: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| - | <code> | + | <code python> |
| left = 0 | left = 0 | ||
| right = len(items) - 1 | right = len(items) - 1 | ||
| Строка 376: | Строка 378: | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| <details> | <details> | ||
| Строка 498: | Строка 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. | ||
| Далее двигаем левый указатель и пропускаем элементы меньше опорного, и ищем неправильный элемент слева. Затем двигаем правый указатель, пропуская элементы больше опорного. | Далее двигаем левый указатель и пропускаем элементы меньше опорного, и ищем неправильный элемент слева. Затем двигаем правый указатель, пропуская элементы больше опорного. | ||
| Строка 504: | Строка 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. Мы снова разбиваем массив на две половины и переходим к упорядочиванию левой и правой половин. | ||
| ==== Как реализовать быструю сортировку ==== | ==== Как реализовать быструю сортировку ==== | ||
| Строка 522: | Строка 532: | ||
| Попробуем реализовать алгоритм на JavaScript. Начнем с функции частичного упорядочивания: | Попробуем реализовать алгоритм на JavaScript. Начнем с функции частичного упорядочивания: | ||
| - | <code> | + | <code javascript> |
| const partition = (items, left, right, pivot) => { | const partition = (items, left, right, pivot) => { | ||
| while (true) { | while (true) { | ||
| Строка 547: | Строка 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: | ||
| Строка 565: | Строка 576: | ||
| right -= 1 | right -= 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 595: | Строка 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) { | ||
| Строка 624: | Строка 639: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| В качестве параметров функция получает: | В качестве параметров функция получает: | ||
| Строка 633: | Строка 649: | ||
| Сначала в цикле пропускаются элементы слева, которые меньше опорного: | Сначала в цикле пропускаются элементы слева, которые меньше опорного: | ||
| - | <code> | + | <code javascript> |
| while (items[left] < pivot) { | while (items[left] < pivot) { | ||
| left += 1; | left += 1; | ||
| Строка 639: | Строка 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 | ||
| Строка 655: | Строка 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; | ||
| Строка 672: | Строка 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 | ||
| Строка 688: | Строка 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> | ||
| Если указатели встретились или зашли друг за друга, мы завершаем цикл и возвращаем место встречи в качестве результата. Нам предстоит разбить массив на два подмассива, поэтому надо решить, что именно возвращать. Мы можем сказать, что граница — это место, где заканчивается левый подмассив, или место, где начинается правый. Большой разницы здесь нет. | Если указатели встретились или зашли друг за друга, мы завершаем цикл и возвращаем место встречи в качестве результата. Нам предстоит разбить массив на два подмассива, поэтому надо решить, что именно возвращать. Мы можем сказать, что граница — это место, где заканчивается левый подмассив, или место, где начинается правый. Большой разницы здесь нет. | ||
| Строка 701: | Строка 729: | ||
| Решим, что функция ''partition'' возвращает индекс элемента, где начинается правый подмассив: | Решим, что функция ''partition'' возвращает индекс элемента, где начинается правый подмассив: | ||
| - | <code> | + | <code javascript> |
| if (left >= right) { | if (left >= right) { | ||
| return right + 1; | return right + 1; | ||
| Строка 707: | Строка 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 | ||
| Строка 723: | Строка 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> | ||
| Если указатели остановились, то они указывают на два элемента в неверном порядке. Левый указатель смотрит на элемент, который больше опорного. При этом правый указатель смотрит на элемент, который меньше опорного. | Если указатели остановились, то они указывают на два элемента в неверном порядке. Левый указатель смотрит на элемент, который больше опорного. При этом правый указатель смотрит на элемент, который меньше опорного. | ||
| Строка 736: | Строка 770: | ||
| Меняем местами и сдвигаем элементы, чтобы в следующей итерации продолжить поиск следующей неправильной пары: | Меняем местами и сдвигаем элементы, чтобы в следующей итерации продолжить поиск следующей неправильной пары: | ||
| - | <code> | + | <code java> |
| const temporary = items[left]; | const temporary = items[left]; | ||
| items[left] = items[right]; | items[left] = items[right]; | ||
| Строка 745: | Строка 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 | ||
| Строка 765: | Строка 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()'' условие становится известно в середине цикла. | ||
| Строка 778: | Строка 818: | ||
| В языках программирования нет специального синтаксиса для такой ситуации. Обычно программисты записывают бесконечный цикл с помощью конструкции ''while (true)'', а выход из цикла делают с помощью операторов ''break'' или ''return'': | В языках программирования нет специального синтаксиса для такой ситуации. Обычно программисты записывают бесконечный цикл с помощью конструкции ''while (true)'', а выход из цикла делают с помощью операторов ''break'' или ''return'': | ||
| - | <code> | + | <code javascript> |
| while (true) { | while (true) { | ||
| // ... | // ... | ||
| Строка 790: | Строка 830: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| <code> | <code> | ||
| Строка 801: | Строка 842: | ||
| # ... | # ... | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 817: | Строка 860: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| while (true) { | while (true) { | ||
| // ... | // ... | ||
| Строка 831: | Строка 876: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Частично упорядоченный массив нельзя назвать полностью отсортированным. Чтобы закончить сортировку, мы должны рекурсивно повторить упорядочивание для левой и правой половин массива. | Частично упорядоченный массив нельзя назвать полностью отсортированным. Чтобы закончить сортировку, мы должны рекурсивно повторить упорядочивание для левой и правой половин массива. | ||
| Строка 836: | Строка 882: | ||
| Про рекурсию мы говорили на прошлом уроке. Так выглядит рекурсивный алгоритм быстрой сортировки. Он немного похож на рекурсивную функцию бинарного поиска: | Про рекурсию мы говорили на прошлом уроке. Так выглядит рекурсивный алгоритм быстрой сортировки. Он немного похож на рекурсивную функцию бинарного поиска: | ||
| - | <code> | + | <code javascript> |
| const sort = (items, left, right) => { | const sort = (items, left, right) => { | ||
| const length = right - left + 1; | const length = right - left + 1; | ||
| Строка 852: | Строка 898: | ||
| </code> | </code> | ||
| - | Python | + | <details> |
| + | <summary>Python</summary> | ||
| <code> | <code> | ||
| Строка 866: | Строка 913: | ||
| sort(items, split_index, right) | sort(items, split_index, right) | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 887: | Строка 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) { | ||
| Строка 911: | Строка 962: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| Для упорядочивания нужно не менее двух элементов. Поэтому мы остановим рекурсивный вызов, когда встретим пустой подмассив или подмассив с одним элементом: | Для упорядочивания нужно не менее двух элементов. Поэтому мы остановим рекурсивный вызов, когда встретим пустой подмассив или подмассив с одним элементом: | ||
| - | <code> | + | <code javascript> |
| const length = right - left + 1; | const length = right - left + 1; | ||
| Строка 931: | Строка 983: | ||
| </code> | </code> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 942: | Строка 995: | ||
| } | } | ||
| </code> | </code> | ||
| + | </details> | ||
| - | Java | + | <details> |
| + | <summary>Java</summary> | ||
| - | <code> | + | <code java> |
| var length = right - left + 1; | var length = right - left + 1; | ||
| Строка 952: | Строка 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); | ||
| Строка 961: | Строка 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 | ||
| Строка 978: | Строка 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> | ||
| Почему мы всегда выбираем самый левый элемент подмассива? | Почему мы всегда выбираем самый левый элемент подмассива? | ||
| Строка 1025: | Строка 1093: | ||
| Чтобы упростить себе жизнь, напишем вспомогательную функцию, которая всегда сортирует массив целиком: | Чтобы упростить себе жизнь, напишем вспомогательную функцию, которая всегда сортирует массив целиком: | ||
| - | <code> | + | <code javascript> |
| const quicksort = (items) => sort(items, 0, items.length - 1); | const quicksort = (items) => sort(items, 0, items.length - 1); | ||
| Строка 1033: | Строка 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) | ||
| Строка 1043: | Строка 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 | ||
| Строка 1058: | Строка 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 { | ||
| Строка 1076: | Строка 1149: | ||
| // => [ 10, 24, 34, 43, 52, 55, 57, 93, 99 ] | // => [ 10, 24, 34, 43, 52, 55, 57, 93, 99 ] | ||
| </code> | </code> | ||
| + | </details> | ||
| Быстрая сортировка намного эффективнее сортировки выбором. Причем эта разница особенно видна на больших массивах. Если сортировать миллион элементов, сортировка выбором окажется медленнее в десятки тысяч раз. | Быстрая сортировка намного эффективнее сортировки выбором. Причем эта разница особенно видна на больших массивах. Если сортировать миллион элементов, сортировка выбором окажется медленнее в десятки тысяч раз. | ||
| Строка 1091: | Строка 1165: | ||
| Сам массив выглядит так: | Сам массив выглядит так: | ||
| - | <code> | + | <code javascript> |
| const products = [ | const products = [ | ||
| { name: "Телевизор", price: 100000, rating: 9.1 }, | { name: "Телевизор", price: 100000, rating: 9.1 }, | ||
| Строка 1105: | Строка 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}, | ||
| Строка 1120: | Строка 1195: | ||
| ] | ] | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1138: | Строка 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), | ||
| Строка 1154: | Строка 1233: | ||
| }; | }; | ||
| </code> | </code> | ||
| + | </details> | ||
| Можно реализовать несколько функций сортировки, но есть и более эффективный способ. Интернет-магазину подойдет **универсальная функция сортировки**. | Можно реализовать несколько функций сортировки, но есть и более эффективный способ. Интернет-магазину подойдет **универсальная функция сортировки**. | ||
| Строка 1163: | Строка 1243: | ||
| Вот так будет выглядеть компаратор, сравнивающий элементы по цене: | Вот так будет выглядеть компаратор, сравнивающий элементы по цене: | ||
| - | <code> | + | <code javascript> |
| const compareByPrice = (item1, item2) => { | const compareByPrice = (item1, item2) => { | ||
| if (item1.price < item2.price) { | if (item1.price < item2.price) { | ||
| Строка 1175: | Строка 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]: | ||
| Строка 1186: | Строка 1267: | ||
| return 1 | return 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1203: | Строка 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"); | ||
| Строка 1220: | Строка 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) { | ||
| Строка 1235: | Строка 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]: | ||
| Строка 1246: | Строка 1333: | ||
| return 1 | return 1 | ||
| </code> | </code> | ||
| + | </details> | ||
| - | PHP | + | <details> |
| + | <summary>PHP</summary> | ||
| - | <code> | + | <code php> |
| <?php | <?php | ||
| Строка 1263: | Строка 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"); | ||
| Строка 1280: | Строка 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) { | ||
| Строка 1296: | Строка 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): | ||
| Строка 1306: | Строка 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 | ||
| Строка 1325: | Строка 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) { | ||