Наступний детермінований (без компаратора) алгоритм працює для вхідного кортежу (а1, … ,ан):
- Зробіть перемішування Фішера-Йейта, використовуючи компаратор зі статичною парою (скажімоa1<a2) у вигляді монети (відбір проб приймання-відхилення). Якщо компаратор виходить1 перший раз, використовуйте його перевернуто, щоб уникнути нескінченного циклу відхилення у детермінованому випадку.
- (Необов’язкове прискорення: спробуйте одну пару n часи, де n- це довжина або ваш вхід. Якщо будь-які два виходи відрізняються, поверніть перестановку, отриману в (1))
- Сортуйте масив за допомогою сортування об'єднань.
Враховуючи детерміновані відношення порядку як компаратора, цей алгоритм сортує масив за часом O(nlogn) оскільки перетасовка Фішера-Йейта пробігає O(n) використовуючи максимальний O(logn)не випадкові "випадкові біти" (наприклад, дзвінки до вашого компаратора) на кожному кроці та сортування злиття мають однакову асимптотичну складність. Результат (1) в цьому випадку абсолютно марний, але оскільки за ним слідує реальний сорт, це не шкодить.
З огляду на справжнє перевертання монет у порівнянні (1) перестановляє масив з однаковою ймовірністю для кожної перестановки, і якщо вам дійсно потрібно зробити (3) (ви вийшли з ладу (2) або (2) не змогли визначити випадковість), це не шкода, оскільки розподіл його результату залежить лише від порядку його введення, який рівномірно розподілений між усіма перестановками через (1), тому результат усього алгоритму також рівномірно розподілений. Геометрично розподіляється кількість повторень відбору вибірки приймання-відхилення (відхилення з вірогідністю)<12) і тому вона має очікувану цінність <2. Кожне повторення використовує максимумlognбіт, тому аналіз виконання майже такі ж , як і в детермінованому випадку, але ми тільки отримати очікуваний час роботи відO(nlogn), з можливістю незахищення (припиняється лише майже напевно ).
Як вказував Джо: Якщо ви не любите тест перший біт в (1), зробіть (3), то (1) і використовуйте an<a1 який є завжди 0, оскільки масив вже відсортований у детермінованому випадку. Крім того, ви повинні відняти випадкове число від верхньої межі діапазону в циклі, оскільки верхня межа для випадкового числа дає однакову перестановку. Але майте на увазі, що (2) заборонено тоді, тому що завжди потрібно робити перетасування у випадку викупу.
Ви навіть можете використовувати ті самі дзвінки до свого порівняльника для (1) та (3), але потім довести, що результат рівномірно розподілений, принаймні набагато складніше, якщо це можливо взагалі.
Наступний алгоритм не має чітких фаз переміщення та сортування, але є асимптотично повільнішим. Це по суті
сортування вставки з
двійковим пошуком . Я буду використовувати
a=(a1,…,an) позначити вхід і
bk=(bk,1,…,bk,k) для позначення результату після
k-й тур:
- Встановити b1,1=a1
- Якщо a2<a1 тоді b2=(a2,a1) і (c,d):=(2,1) ще b2=(a1,a2) і (c,d):=(1,2). В будь-якому випадкуad<ac завжди буде 0 (тобто хибне) для не випадкового порівняння.
- Для отримання bk для k≥3 отримати bk−1 спочатку.
- Дозволяє l=⌈log2k⌉ і k′=2l, тобто k′ - найменша потужність 2 не менше, ніж k.
- Дозволяє i0=0. Для кожногоj∈{1,…,l} дозволяє
ij=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪ij−1+2l−jij−1ij−1+2l−jij−1ij−1+2l−j>k−1∧ad<acij−1+2l−j>k−1∧¬(ad<ac)ij−1+2l−j≤k−1∧bk−1,ij−1+2l−j<akij−1+2l−j≤k−1∧¬(bk−1,ij−1+2l−j<ak)
- Якщо il>k повторити (5.) інше bk=(bk−1,1,…,bk−1,il−1,ak,bk−1,il,…,bk−1,k−1)
- Вихідні дані bn
Випадковий випадок: 5 +, якщо пункт 6 є по суті вибіркою прийняття-відхилення. Решта алгоритму - це наївна перетасовка: перетасувати першуk−1 елементів і додайте k-елемент до кожної позиції з однаковою ймовірністю. Якби ми використовували звичайний сортування вставки, ми отримали б біноміальне розподіл.
Зауважте, що цей алгоритм є неефективним в обох режимах порівняно з перемиканням Fisher-Yates та сортуванням, оскільки вставлення елемента у довільну позицію дороге, якщо для використання масиву та двійкового пошуку потрібен лінійний час, якщо використовується список. Але, можливо, модифікація сортування купи або сортування дерева аналогічним чином може призвести до більш швидкого алгоритму.