Pull to refresh

Comments 40

"Сложно представить, что его не обнаружили раньше" - с "неуловимыми Джо" всегда такая истоия)

Как сейчас помню, этот алгоритм принес на сдачу одноклассник в 11м классе (93 год), я тогда глядя на него так и не смог осознать, почему он работает, учитель, кажется, тоже был в задумчивости. Где он его взял, не представляю, во всех книгах по программированию, которыми мы обменивались, его не было, интернета тоже не было. Я тогда что-то не спросил, решил что придумал самостоятельно, восхитился (на бумаге выглядит красиво и абсолютно неочевидно). Поэтому как минимум один человек обнаружил его в 1993 году :)

Но сейчас все же думаю что посмотрел где-то или кто-то подсказал

Выглядит не как ошибочный, а как пузырёк, в который забыли добавить убывание на 1 элемент на каждом следующем проходе. Скажите сразу, в чём отличие от пузырька, а то не очень пока понятно нужно ли читать целиком статью.

ну, промолотит циклы лишние 100500 раз — банальным пузырьком от этого быть не перестанет.

У пузырьковой сортировки меняются местами соседние элементы, а тут два независимых индекса.

Да мне кажется каждый изобретал что-то похожее, если его спрашивали можно ли оптимизировать пузырёк.

Точно, именно таким алгоритмом я пользовался, когда решал простые задачки в универе на с++, тогда и не знал что другие вообще существуют, кроме пузырьковой.

Всё просто , нет смысла проходить по уже отсортированным, элементам, поэтому во вложенном цикле i=j.

Да, алгоритм сравнительно не эффективен, но для малых чисел очень полезен.

а тут два независимых индекса.
Сначала показалось что это больше похоже на сортировку выбором с лишними перестановками и лишними сравнениями.
Но на самом деле нет
— Сначала ухудшаем сортировку выбором делая лишние перестановки (чтобы не запоминать номер самого большого числа).
— Потом ухудшаем получившийся алгоритм делая лишние сравнения, но тут вся схожесть теряется. Получается магия, потому что элементы не только сортируются в обратном порядке, но и за индексом i протягивается отсортированный хвост каким-то другим алгоритмом еще одной сортировкой выбором с лишними перестановками… omg
пример прогона
369852147
|
639852147
936852147
.|
936852147
396582147
..|
396582147
369582147
...|
369582147
365982147
....|
365982147
365892147
.....|
365892147
265893147
235896147
235698147
235689147
......|
235689147
135689247
125689347
123689547
123589647
123569847
123568947
.......|
123568947
123468957
123458967
123456987
123456897
........|
123456897
123456798
123456789


О, это очень прикольный алгоритм, и у меня реакция была такой же, когда я первый раз видел статью.
Он, конечно, неэффективный, никто ни спорит
Но прикольным этот алгоритм становится именно тогда, когда пытаешься доказать его корректность.

Смотрите: стандартная сортировка вставками за n^2 устроена так, что каждый раз сравниваются i-й и j-й элементы массива, где i < j. Соответственно после каждого сравнения число инверсий уменьшается.

for i from 0 to n:
  for j from i to n:
    if a[i] > a[j]:
      swap(a[i], a[j])

А в алгоритме из статьи оба цикла от 1 до n, поэтому, иногда (если i > j) алгоритм переставляет элементы, которые уже в правильном порядке. А теперь попробуйте доказать, что после этих операций массив будет отсортирован. Вот и получаем симпатичное упражнение по комбинаторике=)

Я бы ещё во всех этих алгоритмах не сравнивал a[i] с a[j] , когда i==j

for i from 0 to n:
  for j from i+1 to n:
  	if i != j:
    	if a[i] > a[j]:
	      swap(a[i], a[j])

Но ведь конкретно в этом случае j>iиз цикла на второй строчке. Они не могут быть равны.

А для алгоритима из статьи лишнее условие совсем не нужно, оно лишь впустую его усложнит, как мне думается (всё равно никто же не собирается использовать его?).

Это псевдокод - его точно каждый может скомпилировать... в голове=)

Если так, то тогда не вижу приемуществ псевдокода перед кодом JS (например).
Представьте что вы читаете другой псевдокод, где операторы равенства находятся наоборот слева, а переменная равенства справа. Вам бы пришлось бы в голове каждый раз переворачивать формулы. Но такие операторы равенства используются в простой математике. Но если бы был синтаксис который вообще не знаком, это напрягает.

  • Преимущество псевдокода перед кодом JS - в отсутствии ===, безумной системы приведения типов, увлекательных приключений this и т.д.

  • Преимущество псевдокода перед С - в отсутствии черной магии при работе с памятью.

  • Преимущество псевдокода перед питоном, например, в том, что from 1 to n понятнее чем range(1, n+1)- к слову, он значительно ближе к псевдокоду, чем JS и С.

Смысл в том, что мы обсуждаем не детали реализации алгоритма на конкретном языке, а сам алгоритм. В этом случае его удобнее записывать так, чтобы он был понятен любому человеку знакомому с азами программирования и вне зависимости от известного читателю ЯП.

P.S. Единого синтаксиса для псевдокода нет, так что вы вполне можете перевернуть операторы равенства - главное, чтобы результат всё ещё очевидно понимался большей частью людей.

Может быть псевдокод имеет приемущество в каких-то ситуациях, но тут нет ни this, ни ===, ни ==.

i == j всего n раз, в случае со сложность n**2 это не так критично по моему)

function sort (arr) {
  for (let i = 1, l = arr.length; i < l; i++) {
    for (let j = 0; j <= (i - 1); j++) {
      if (arr[i] < arr[j]) {
        [arr[i], arr[j]] = [arr[j], arr[i]]
      }
    }
  }
}

Спасибо огромное.
думаю можно упростить: j <= (i - 1) к j < i
Спасибо еще раз.

верно, поздно увидел. а коментировать могу только раз в 24 часа :)

function sort (arr) {
  for (let i = 1, l = arr.length; i < l; i++) {
    for (let j = 0; j < i; j++) {
      if (arr[i] < arr[j]) {
        [arr[i], arr[j]] = [arr[j], arr[i]]
      }
    }
  }
}

Этот "простой" алоритм сортировки - сильно прожорливый О(n^2)

Как и пузырёк. За простоту приходится платить.

А че за нее платить, запилил нормальный алгоритм, засунул в функцию и пользуешь. Тоже достаточно просто с учетом того, что готовых решений уже полно

Готовых решений... на вашем любимом языке под вашу привычную платформу?

Вообще некоторые алгоритмы имеют не столько практическую, сколько теоретическую ценность. А некоторые полезны в педагогических целях. Приведённый в статье (как и оригинальный пузырёк), имеет именно педагогическую ценность, поэтому "засунул в функцию и пользуешь" - не релевантно.

Я ещё со школы запомнил и способен написать сортировку слиянием под любой язык, регулярно это делаю в качестве упражнения. Но мне интересно - что это у вас за любимые языки (и платформы) такие, что на них нет стандартных реализаций того же квиксорта?

Я ещё со школы запомнил и способен написать сортировку слиянием под любой язык, регулярно это делаю в качестве упражнения.

Это прекрасно, но какое это отношение имеет к моему сообщению?

Но мне интересно - что это у вас за любимые языки (и платформы) такие, что на них нет стандартных реализаций того же квиксорта?

Раз уж спросили (не знаю, зачем), мои любимые языки - С++ и Python, на них есть всё что мне нужно. Но иногда приходится работать на платформах, где нет ни плюсов, ни питона (в эмбеде такое часто). А есть только какой-то ассемблер или урезанный С. И на весь программный машинный код у вас 16 килобайт. И когда ты заранее знаешь, что будешь сортировать массивы на 50 элементов, то заморачиваться с квиксортом на ассемблере совсем не хочется. Да, такое редко встречается, но всё ещё не вымерло.

Не имеет. Алгоритм работает неочевидным образом, для объяснений не особо. С этим можно было бы смириться, если бы он был эффективнн, но нет.

Согласен, что его результат неочевиден, но на мой взгляд это было бы прекрасным домашним заданием вида "а вот такая штука - сортировка или нет?" Он не слишком зубодробительный (всего 4 строки, Карл!), но при этом требуется некая аккуратность для строгого доказательства. По-моему, для студентов младших курсов - идеально, т.к. надо не только знать хорошие алгоритмы, но и научиться проверять "неизвестные" алгоритмы на предмет корректности.

Заменой 1 символа алгоритм из непрозрачного превращается в абсолютно прозрачный алгоритм сортировки максимумом (ну и заодно ускоряется вдвое).

Да, всё верно. Вы много пользы видите от того, чтобы в качестве самостоятельных заданий давать что-то очевидное и прозрачное?

Да, много. Программист должен видеть очевидные и прозрачные алгоритмы и стремиться к ним: его код потом кому-то читать.

Вот как задачка по математике сошло бы.

Он хуже пузырька почти всегда

Корявая реализация сортировки максимумом. Не стОит статьи, и уж удивляться, что работает – нелепо.

Upd: я облажался. Всё ещё не стоит статьи, но это не сортировка максимумом.

Не уверен что тут может вызывать удивление? По сути имеем кривую, хоть и довольно простую, сортировку выбором. Плюс явный косяк в выборе индексов. j нет смысла пробегать всё что идёт до i включительно. А i нет смысла заходить в последний элемент.

Я честно не понимаю, что тут может хоть как-то удивлять? И уж тем более не понимаю, почему кто-то с какого-то перепугу решил, что это "потерянное" и "недостающее" звено в эволюции древних сортировок которое по какой-то "неизведанной" причине проморгали великие умы древности.

У вас все 3 вычислительные сложности обозначены как большая тета, хотя это только про среднюю сложность. Худший случай обозначается большой О, лучший - большой омегой.

Самый простой (и неожиданный) алгоритм сортировки?

Действительно неожиданный. Ожидал увидеть stalin-sort :D

Визуализировал эту сортировку

Sign up to leave a comment.