Чи є гірші алгоритми сортування, ніж Bogosort (він же Сортування мавп)? [зачинено]


178

Мої колеги відвели мене назад у часі до університетських днів із обговоренням алгоритмів сортування цього ранку. Ми нагадали про наших улюблених, як StupidSort , і один із нас був впевнений, що бачив такий собі алгоритм O(n!). Це мене почало шукати навколо "найгірших" алгоритмів сортування, які я міг знайти.

Ми постулювали, що абсолютно випадковий сортування буде досить поганим (тобто рандомізувати елементи - це в порядку? Ні? Знову рандомізувати), і я озирнувся і дізнався, що його, мабуть, називають BogoSort, або Сортування мавп, або іноді просто випадкове сортування .

Здається, сортування мавп має найгірший показник O(∞), найкращий показник O(n)і середню ефективність O(n·n!).

Який офіційно прийнятий в даний час алгоритм сортування з найгіршими середніми показниками сортування (а отже, гірший O(n·n!))?


10
Скільки богоміпів на богосорта? Допитливі розуми хочуть знати.
зомбат

13
Для уточнення, ви виключаєте тривіальний випадок, коли найкраща ефективність випадку O (∞)?
tloflin


6
Я чув, що сорт мавп також відомий як "п’яний сорт чоловіка", ім'я, яке я вважаю набагато спритнішим.
Matteo Italia

6
@Matteo Italia - або це можна назвати "сортування малюка", як це може засвідчити кожен із 2-річного віку.
Мартін Каподічі

Відповіді:


442

З сторінки езотеричних алгоритмів Девіда Морган-Мар : Інтелектуальний сортування дизайну

Вступ

Інтелектуальний сорт дизайну - алгоритм сортування, заснований на теорії інтелектуального дизайну.

Опис алгоритму

Ймовірність того, що оригінальний список введення буде в точному порядку, у якому він є, є 1 / (n!). Існує така мала ймовірність цього, що говорити про те, що це сталося випадково, очевидно, тому це, мабуть, було свідомо введено в цей порядок розумним сортером. Тому можна припустити, що воно вже оптимально відсортовано певним чином, що перевершує наше наївне смертне розуміння "порядку зростання". Будь-яка спроба змінити цей порядок, щоб він відповідав нашим власним попередженням, насправді зробить його менш упорядкованим.

Аналіз

Цей алгоритм є постійним у часі і сортує список на місці, не вимагаючи взагалі додаткової пам'яті. Насправді, він навіть не вимагає будь-яких із цих підозрілих технологічних комп'ютерних матеріалів. Похваліть сортувальника!

Відгуки

Гері Роджерс пише:

Здійснення сортування постійним у часі заперечує силу Сортера. Сортер існує поза часом, таким чином сортування є вічним. Щоб вимагати часу на перевірку сортування, зменшується роль сортувальника. Таким чином ... цей конкретний сорт є хибним, і його не можна віднести до "сортувальника".

Єресь!


94
Також відомий як "Сортування припущення": Припустимо, що список відсортований, повертайся!
BioGeek

42
+100 - ця відповідь складається з 100% чистого виграшу.
утроба

11
Гей! Не забувайте "Нерішучий сортування" (також відомий як "Сортування Шредінгера" або "Квантове сортування"), де список може бути, а може і не бути відсортованим, проте перевірка його виявить, чи є він. Ось мій приклад реалізації: void quantum_sort (void *b, size_t n, size_t s, int (*c)(const void *, const void*)) { if (rand () % 2) qsort (b, n, s, c); }.
Джо D

6
Ми повинні перезаписати цей Кандид Сортувати :"This is the best of all posibble worlds because it is the world that is, and so in the best possible world the array would already be sorted!"
echochamber

2
Я, наприклад, вітаю наш новий дистрибутор. Всі вітайте сортувальника!
Брайсон

299

Багато років тому я винайшов (але ніколи фактично не реалізований) MiracleSort.

Start with an array in memory.
loop:
    Check to see whether it's sorted.
    Yes? We're done.
    No? Wait a while and check again.
end loop

Зрештою, альфа-частинки, що перегортають біти в мікросхемах пам'яті, повинні призвести до успішного сортування.

Для більшої надійності скопіюйте масив у захищене місце та перевірте потенційно відсортовані масиви щодо оригіналу.

Отже, як перевірити потенційно відсортований масив щодо оригіналу? Ви просто сортуєте кожен масив і перевіряєте, чи вони відповідають. MiracleSort - це очевидний алгоритм, який слід використовувати для цього кроку.

EDIT: Строго кажучи, це не алгоритм, оскільки його не гарантовано припиняється. Чи не "алгоритм" кваліфікується як "гірший алгоритм"?


39
Я припускаю, що можна використовувати космічні промені, щоб довести правильність цього алгоритму.
ghord

1
Що великого O цього? O(2^N)?
Mooing Duck

12
@MooingDuck: Я не думаю, що насправді це великий О.
Кіт Томпсон,

5
@MooingDuck: Власне кажучи, якщо це не припиняється, це не алгоритм, відповідно до того, що вони навчали мене в коледжі та статті Вікіпедії .
Кіт Томпсон,

7
@Olathe: Проблема зупинки говорить, що ми не можемо визначити, чи всі вони зупиняються, але є багато програм, за якими ми можемо визначитись із цим. Ми знаємо, що Quicksort і Bubblesoft зупиняються, і ми знаємо, що це алгоритми.
Кіт Томпсон

133

Квантовий Богосорт

Алгоритм сортування, який передбачає, що багатосвітове тлумачення квантової механіки є правильним:

  1. Перевірте, чи список відсортований. Якщо ні, руйнуйте Всесвіт.

Після закінчення алгоритму список буде відсортований у єдиному всесвіті, що залишився. Цей алгоритм займає найгірший O (N) та середній регістр O (1). Насправді, середня кількість проведених порівнянь становить 2: є 50% шансів, що Всесвіт буде знищений на другому елементі, 25% шансів, що він буде знищений на третьому тощо.


42
Але час перестає існувати у Всесвіті, який ви щойно зруйнували. Тож спостерігач у Всесвіті, який ви ще не перевірили, не зможе сказати, яка частина алгоритму виконана. Таким чином, цей алгоритм завжди займає O (1) час, оскільки попередніх руйнувань Всесвіту вже не існує.
Баррі Браун

12
Так, в єдиному Всесвіті, який спостерігає за відсортованим списком, потрібно було виконати O (n) час - скільки часу пройшло в інших всесвітах, не має значення.
Нік Джонсон

19
Однак цей алгоритм має набагато більшу проблему. Припустимо, що один з 10 мільярдів разів ви помилково зробите висновок, що список відсортований, коли його немає. Є 20! способи сортування списку 20 елементів. Після сортування решта всесвітів буде тим, у якому список був відсортований правильно, а 2,4 мільйони всесвітів, в яких алгоритм помилково зробив висновок, був відсортований правильно. Отже, у вас тут є алгоритм масового збільшення коефіцієнта помилок у частині техніки.
Нік Джонсон

10
Це, очевидно, найкращий алгоритм сортування, а не найгірший.
Боан

11
Якщо не очолити пораду Жука, це може призвести до знищення всіх всесвітів.
CrashCodes

60

Я здивований, що ще ніхто не згадав про сплячку ... Або я цього не помітив? У будь-якому випадку:

#!/bin/bash
function f() {
    sleep "$1"
    echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait

Приклад використання:

./sleepsort.sh 5 3 6 3 6 3 1 4 7
./sleepsort.sh 8864569 7

З точки зору продуктивності це жахливо (особливо другий приклад). Чекати майже 3,5 місяця, щоб сортувати 2 номери, це щось погано.


3
Це здається , щоб бути свого O(N)роду, але насправді обмежується , проте ОС знарядь таймерів.
Mooing Duck

7
Будь-який спосіб вирізати, це, мабуть, демонструє кращий ріст, ніж богосорт.
Mooing Duck

8
Я бачу там стан перегонів.

5
Ви можете змінити sleep "$1"на, sleep "0.$(printf "%010d" $1)"щоб поліпшити продуктивність помітно. time ./sleepsort.sh 8864569 7потім працює на 0,009с на моєму ноутбуці.
Сем Келлетт

1
Це працює у складності O (N) (звичайно, залежно від впровадження таймера), це просте сортування відра в іншій формі.
Qwerty01

60

Сортування Jingle, як описано тут .

Ви даєте кожне значення у своєму списку іншій дитині на Різдво. Діти, будучи жахливими людьми, порівнюють цінність своїх подарунків і відповідно сортують себе.


50

У мене був лектор, який одного разу запропонував генерувати випадковий масив, перевіряючи, чи він відсортований, а потім перевіряє, чи дані збігаються з масивом для сортування.

Найкращий випадок O (N) (перший раз дитина!) Найгірший випадок O (ніколи)


4
Більш цікавим для аналізу є середній випадок , який є ...?
Mooing Duck

4
Як кажуть всі найкращі підручники з текстами, це залишається як вправа для читача!
Даніель

40
Mooing Duck: O (інколи)
Ілля О.

1
@MooingDuck тоді нам потрібно знати кардинальність типу елементів і розподілу, які використовуються для генерації випадкових елементів у випадкових масивах.
Відображати ім’я

5
Складність становить O (N! * Z ^ N), де Z - розмір набору можливих значень, а N - довжина масиву.
jakubiszon

30

Якщо будь-який спосіб тримати алгоритм значущим, O(n!)це найгірша верхня межа, яку ви можете досягти.

Оскільки перевірка кожної можливості для сортування перестановок набору буде вживати n!кроків, ви не можете отримати гірше за це.

Якщо ви робите більше кроків, ніж це, то алгоритм не має реальної корисної мети. Не кажучи вже про такий простий алгоритм сортування з O(infinity):

list = someList
while (list not sorted):
    doNothing

14
Але потрібно O (n), щоб перевірити, чи сортується він, тож ви можете отримати O (n * n!)
erikkallen

3
@erikkallen: Безумовно, ми можемо придумати алгоритм для перевірки сортування, що гірше, ніж O (n). Наприклад, для кожного елемента масиву переконайтеся, що він більший за всі попередні, як і сортування вставки. Це алгоритм O (n ^ 2), і я впевнений, що міг би придумати гірше, якщо трохи подумати.
Девід Торнлі

7
@David Thornley: наступний алгоритм перевірки, можливо, виявить такий самий дух, як і богосорт: виберіть два випадкових елемента, перевірте, чи той, який має менший індекс, менший чи рівний тому, який має більший індекс, і повторіть. Зберігайте квадратну бітову матрицю, щоб побачити, які комбінації вже перевірені. Звичайно, перевірку цієї матриці можна було б зробити і випадковою прогулянкою ...
Svante

19

Богобогосорт. Так, це річ. до Богобогосорту, ви Богоссорт перший елемент. Перевірте, чи сортується цей один елемент. Будучи одним із елементів, так і буде. Потім ви додаєте другий елемент і Богосорт цих двох, поки не буде відсортовано. Потім ви додаєте ще один елемент, а потім Богосорт. Продовжуйте додавати елементи та Bogosorting, поки ви нарешті не зробите кожен елемент. Це було покликане ніколи не досягти успіху в жодному значному списку до теплової смерті Всесвіту.


5
Свята мати коду. Я думаю, що ми навіть можемо зробити короткий Боголплекс.
MrKekson

19

Вам слід зробити кілька досліджень у захоплюючому полі песимальних алгоритмів та простоти аналізу . Ці автори працюють над проблемою розробки сорту з песимальним найкращим випадком (найкращий випадок вашого богосорта - Омега (n), тоді як уповільнення (див. Папір) має складну часову складність не поліноміального).


19

Існує різновид, який називається богобогозор. По-перше, він перевіряє перші 2 елементи та богосортує їх. Далі він перевіряє перші 3, богосортує їх тощо.

Якщо список не вийде з ладу в будь-який час, він буде перезапущений шляхом повторного запуску перших 2. Регулярний богосорт має середню складність O(N!), цей алгоритм має середню складністьO(N!1!2!3!...N!)

Редагувати : щоб дати вам уявлення про те, наскільки велика ця кількість, для 20елементів цей алгоритм займає в середньому 3.930093*10^158 років , що значно перевищує запропоновану теплову смерть Всесвіту (якщо це станеться) 10^100 років ,

тоді як сортування злиття займає близько .0000004 секунд , сортування бульбашок .0000016 секунд , а богосорт займає 308 роки , 139 дні , 19 години , 35 хвилини , 22.306 секунди , якщо припустити, що рік становить 365,242 дня, а комп'ютер робить 250 000 000 32-бітових цілих операцій в секунду.

Edit2 : Цей алгоритм не такий повільний, як диво-сортування «алгоритм», який, ймовірно, подібний сорту, отримає комп'ютер, засмоктаний у чорну діру, перш ніж він вдало сортує 20 елемнтів, але якби це було, я б оцінив середню складність від 2^(32(the number of bits in a 32 bit integer)*N)(the number of elements)*(a number <=10^40) років ,

оскільки гравітація прискорює переміщення альфа-чіпів, і є 2 ^ N станів, що є 2^640*10^40, або приблизно 5.783*10^216.762162762 років , хоча якби список розпочався сортованим, його складність була б лише O(N)швидшою, ніж сортування злиття, яке є лише N log N навіть в гіршому випадку

Edit3 : Цей алгоритм дійсно повільніше , ніж чудо то , як розмір стає дуже великим, скажімо , 1000, так як мій алгоритм буде мати час виконання 2.83*10^1175546 років , в той час як алгоритм диво начебто час роботи 1.156*10^9657 років .


1
чудово попрацював відповідь. сумно, це не має видимість
swyx

16

Ось два види, які я придумав зі своїм сусідом по кімнаті в коледжі

1) Перевірте порядок 2) Можливо, сталося диво, перейдіть до 1

і

1) перевірте, чи це в порядку, якщо ні, 2) покладіть кожен елемент у пакет і відмовте його від віддаленого сервера назад до себе. Деякі з цих пакетів повернуться в іншому порядку, тому перейдіть до 1


Другий - майже еквівалент сорту bozo. По-перше, це розумно.
Mooing Duck

1
Перший - Чудо Сортування.
Чарльз

14

Завжди є Богобогосорт (Богоцепція!). Він виконує Bogosort на все більших підмножинах списку, а потім починається все заново, якщо список ніколи не сортується.

for (int n=1; n<sizeof(list); ++n) {
  while (!isInOrder(list, 0, n)) {
    shuffle(list, 0, n);
  }
  if (!isInOrder(list, 0, n+1)) { n=0; }
}

5
Мені подобається думка, що цей алгоритм розроблений так, щоб ніколи не закінчуватись "до теплової загибелі Всесвіту для будь-якого значного списку"
А.Грандт

10

1 Поставте свої предмети для сортування на покажчикові картки
2 Киньте їх у повітря у вітряний день, за милю від вашого будинку.
2 Киньте їх у багаття і переконайтесь, що вони повністю знищені.
3 Перевірте кухонну підлогу на правильність замовлення.
4 Повторіть, якщо це не правильний порядок.

Найкращий сценарій - O (∞)

Редагування вище на основі проникливого спостереження від KennyTM.


9
Ні, це гірше, тому що немає шансів на те, що це вдасться. Як би вказівні картки потрапили на вашу кухню? Вони дмуть назовні. Це називається, але, головне.
Патрік Карчер

Я думаю, що він означає викинути карти назовні , а потім перевірити свою підлогу всередині , де гарантовано не буде карт. Хоча це не "названий" алгоритм ... це, звичайно, гірше!
утроба

10
@Panrick Quantum тунелювання.
kennytm

8
@KennyTM. Це мені насправді прийшло в голову. Є надзвичайно малий, але ненульовий шанс, що будь-який об’єкт може зникнути і з’явитися знову в будь-якій іншій точці Всесвіту. Я здогадуюсь, це може статися з тисячею індексних карт. . . Ой. Дангіт, мій алгоритм хибний . Я це виправлю. . .
Патрік Карчер

3
Це як би пити чай і не пити одночасно. Або космічні подорожі, використовуючи нескінченний привід неймовірності.
Баррі Браун

9

"Що б ви хотіли, щоб це було?" сортувати

  1. Зверніть увагу на системний час.
  2. Сортувати за допомогою Quicksort (або будь-якого іншого розумного сенсу), опустивши останній своп.
  3. Зверніть увагу на системний час.
  4. Обчисліть необхідний час. Розширена арифметика точності - це вимога.
  5. Зачекайте необхідний час.
  6. Зробіть останній своп.

Він не тільки може реалізувати будь-яке мислиме значення O (x), не обмежене нескінченність, витрачений час є вірогідно правильним (якщо ви можете чекати так довго).


8

Ніщо не може бути гірше, ніж нескінченність.


38
Нескінченність + 1. Jinx, без повернення.
зомбат

24
Не для надзвичайно великих значень 1;)
зомбат

8
Що насправді роздуває мою концепцію нескінченності, це те, що ти можеш мати різні "розміри" нескінченності. Наприклад, розглянемо набір усіх цілих чисел - він нескінченний за розміром. Тепер розглянемо множину всіх парних цілих чисел - вона також нескінченна за розміром, але також явно наполовину менша за перший набір. Обидва нескінченні, але різної величини. Такий чудовий. Поняття "розмір" просто не працює в контексті нескінченності.
зомбат

4
@zombat: Ви говорите про кардинальність, а не нескінченність як символ, що вказує на тенденцію на реальній лінії / складному площині.
kennytm

18
@zombat. Розмір набору парних цілих чисел такий самий, як і розмір безлічі цілих чисел, що свідчить про те, що ви можете розмістити їх у відповідності один до одного. Тепер є більш реальні числа, ніж цілі числа, як вперше показав Кантор.
Девід Торнлі

5

Сортування Bozo - це пов’язаний алгоритм, який перевіряє, чи список відсортований, а якщо ні - то заміняє два елементи навмання. У нього такі ж найкращі та найгірші виступи, але я інтуїтивно очікую, що середній випадок буде довшим, ніж у Богосорта. Важко знайти (або створити) будь-які дані про продуктивність цього алгоритму.


5

Відрізки π

Припустимо, π містить усі можливі кінцеві комбінації чисел. Дивіться питання math.stackexchange

  1. Визначте кількість розрядів, необхідних від розміру масиву.
  2. Використовуйте сегменти π місць як індекси, щоб визначити, як переупорядкувати масив. Якщо відрізок перевищує межі розмірів для цього масиву, відрегулюйте π десяткове зміщення та почніть спочатку.
  3. Перевірте, чи відсортований повторно замовлений масив. Якщо це не так, інакше відрегулюйте зміщення та почніть спочатку.

4

Найгірший продуктивність випадок O (∞) не може навіть зробити його алгоритм в відповідно до деякими .

Алгоритм - це лише ряд кроків, і ви завжди можете зробити гірше, трохи підправивши його, щоб отримати бажаний результат у більшій кількості кроків, ніж раніше. Можна було б навмисно вкласти знання про кількість кроків, зроблених в алгоритмі, і змусити його закінчуватись і виробляти правильний висновок лише після Xтого, як буде виконано кількість кроків. Це Xможе бути цілком порядком O (n 2 ) або O (n n! ) Або будь-яким алгоритмом, який потрібно зробити. Це фактично збільшило б найкращі, а також середні межі.

Але найгіршого сценарію неможливо досягти :)


3

Мій улюблений алгоритм повільного сортування - це сортування:

void stooges(long *begin, long *end) {
   if( (end-begin) <= 1 ) return;
   if( begin[0] < end[-1] ) swap(begin, end-1);
   if( (end-begin) > 1 ) {
      int one_third = (end-begin)/3;
      stooges(begin, end-one_third);
      stooges(begin+one_third, end);
      stooges(begin, end-one_third);
   }
}

Найгірший складний випадок O(n^(log(3) / log(1.5))) = O(n^2.7095...).

Ще один алгоритм повільного сортування насправді називається slowsort!

void slow(long *start, long *end) {
   if( (end-start) <= 1 ) return;
   long *middle = start + (end-start)/2;
   slow(start, middle);
   slow(middle, end);
   if( middle[-1] > end[-1] ) swap(middle-1, end-1);
   slow(start, end-1);
}

Цей приймається O(n ^ (log n))в кращому випадку ... навіть повільніше, ніж стогерорт.


3
Recursive Bogosort (probably still O(n!){
if (list not sorted)
list1 = first half of list.
list 2 = second half of list.
Recursive bogosort (list1);
Recursive bogosort (list2);
list = list1 + list2
while(list not sorted)
    shuffle(list);
}

2

Цю сторінку цікаво читати на тему: http://home.tiac.net/~cri_d/cri/2001/badsort.html

Мій особистий фаворит - дурний торт Тома Даффа:

/*
 * The time complexity of this thing is O(n^(a log n))
 * for some constant a. This is a multiply and surrender
 * algorithm: one that continues multiplying subproblems
 * as long as possible until their solution can no longer
 * be postponed.
 */
void sillysort(int a[], int i, int j){
        int t, m;
        for(;i!=j;--j){
                m=(i+j)/2;
                sillysort(a, i, m);
                sillysort(a, m+1, j);
                if(a[m]>a[j]){ t=a[m]; a[m]=a[j]; a[j]=t; }
        }
}

2

Подвійний богосорт

Двічі Богосорт і порівняйте результати (тільки щоб переконатися, що він відсортований), якщо не робити це знову


1

Ви можете зробити будь-який алгоритм сортування повільніше, виконавши свій крок "це сортовано" випадковим чином. Щось на зразок:

  1. Створіть масив booleans такого ж розміру, як масив, який ви сортуєте. Встановіть їх на значення false.
  2. Виконайте ітерацію богосорту
  3. Виберіть два випадкових елемента.
  4. Якщо два елементи відсортовані по відношенню до іншого (i <j && масив [i] <масив [j]), позначте індекси обох булевих масивів до істинних. Крім того, починайте спочатку.
  5. Перевірте, чи справді всі булеві масиви. Якщо ні, поверніться до 3.
  6. Зроблено.

1

Так, SimpleSort, теоретично він працює, O(-1)однак це еквівалентно тому,O(...9999) що в свою чергу еквівалентно O (∞ - 1), що, як це відбувається, також еквівалентно O (∞). Ось мій зразок реалізації:

/* element sizes are uneeded, they are assumed */
void
simplesort (const void* begin, const void* end)
{
  for (;;);
}

1

Один, над яким я тільки працював, передбачає вибір двох випадкових точок, і якщо вони в неправильному порядку, перевертати весь піддіапазон між ними. Я знайшов алгоритм на http://richardhartersworld.com/cri_d/cri/2001/badsort.html , який говорить, що середній випадок, ймовірно, десь біля O (n ^ 3) або O (n ^ 2 log n) ( він не дуже впевнений).

Я думаю, що це можливо зробити це більш ефективно, тому що я думаю, що це могло б зробити операцію розвороту за O (1) час.

Власне, я просто зрозумів, що це зробить все, про що я говорю, можливо, тому що я просто зрозумів, що структура даних, яку я мав на увазі, покладе доступ до випадкових елементів у O (log n) та визначить, чи потрібно воно реверсувати на O (n ).


1

Randomsubsetsort.

Дано масив з n елементів, виберіть кожен елемент з вірогідністю 1 / n, рандомізуйте ці елементи та перевірте, чи масив сортується. Повторюйте, поки не сортуєте.

Очікуваний час залишається як вправа для читача.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.