Следующий детерминированный (без компаратора) алгоритм работает для входного кортежа :(a1,…,an)
- Выполните Fisher-Yates перемешайте с помощью компаратора с некоторой статической парой (скажем , ) в качестве подбрасывания монеты (делают выборку приемо-отказ). Если компаратор выдает 1 в первый раз, используйте его инвертированным, чтобы избежать бесконечного цикла отклонения в детерминированном случае.a1<a21
- (необязательное ускорение: попробуйте одну пару раз, где n - длина или ваш вход. Если какие-либо два выходных сигнала отличаются, возвращают перестановку, полученную в (1))nn
- Сортируйте массив, используя сортировку слиянием.
При наличии детерминированного отношения порядка в качестве компаратора этот алгоритм сортирует массив за время поскольку перемешивание Фишера-Йейтса выполняется в O ( n ) с использованием максимального O ( log n).O (nlogн )O (n)случайная ) неслучайных «случайных битов» (например, вызовов вашего компаратора) ) в каждом шаге сортировка слиянием имеет одинаковую асимптотическую сложность. Результат (1) в этом случае совершенно бесполезен, но поскольку за ним следует реальная сортировка, это не вредит.O (журналн )
Учитывая реальный бросок монеты, когда компаратор (1) переставляет массив с равной вероятностью для каждой перестановки, и если вам действительно нужно сделать (3) (вы пропустили (2) или (2) не смогли определить случайность), это не вред, потому что распределение его результата зависит только от порядка его ввода, который равномерно распределен среди всех перестановок из-за (1), поэтому результат всего алгоритма также равномерно распределен. Количество раз, которое каждая повторная выборка-приемка должна быть геометрически распределена (отклонение с вероятностью ) и, следовательно, имеет ожидаемое значение<2. Каждоеиспользует повторение в большинствелогапбит, поэтому анализ выполнения почти такие жекакв детерминированном случае, но мы получить толькоожидаемое время работыотO(павторизуйтесьп), с возможностью nontermination (только прекращает< 12< 2журналNO (nlogн ) почти наверное ).
Как Джо отметил: Если вам не нравится , тест на первый бит в (1), делать (3) , затем (1) и использовать , который всегда 0 , так как массив уже отсортирован в детерминированный случай. Кроме того, вы должны вычесть ваше случайное число из верхней границы диапазона в цикле, потому что верхняя граница для случайного числа дает идентичную перестановку. Но имейте в виду, что (2) тогда запрещено, потому что вы всегда должны делать случайные действия в случае выкупа.aN<a10
Вы даже можете использовать те же вызовы для вашего компаратора для (1) и (3), но затем доказать, что результат распределен равномерно, как минимум, намного сложнее, если вообще возможно.
Следующий алгоритм не имеет отдельных фаз для перемешивания и сортировки, но асимптотически медленнее. Это по сути
вставка сортировки с
бинарным поиском . Я буду использовать
для обозначения ввода, а
b k = ( b k , 1 , … , b k , k ) для обозначения результата после
k-го раунда:
а = ( а1, ... ,N)бК= ( бк , 1,…,bk,k)k
- Установите b1,1=a1
- Если то b 2 = ( a 2 , a 1 ) и ( c , d ) : = ( 2 , 1 ), иначе b 2 = ( a 1 , a 2 ) и ( c , d ) : = ( 1 , 2 ) . В любом случае a d <a2<a1b2=(a2,a1)(c,d):=(2,1)b2=(a1,a2)(c,d):=(1,2) всегда будет 0 (т. е. false) для неслучайного компаратора.ad<ac0
- Чтобы получить при k ≥ 3, сначала получим b k - 1 .bkk≥3bk−1
- Пусть и k ′ = 2 l , т.е. k ′ - наименьшая степень 2, не меньшая, чем k .l=⌈log2k⌉k′=2lk′2k
- Пусть . Для каждого j ∈ { 1 , … , l } пусть
i j = { i j - 1 + 2 l - j i j - 1 + 2 l - j > k - 1 ∧ a d < a c i j - 1 i j - 1 + 2 л -i0=0j∈{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)
- Если повторите (5.) иначе b k = ( b k - 1 , 1 , … , b k - 1 , i l - 1 , a k , b k - 1 , i l , … , b k - 1 , к - 1 )il>kbk=(bk−1,1,…,bk−1,il−1,ak,bk−1,il,…,bk−1,k−1)
- Выход bn
Случайный случай: 5 + условие if из 6 - это, по сути, выборка принятия-отклонения. Остальная часть алгоритма - наивный случайный порядок: перемешайте первые элементов и добавьте kk−1k элемент в каждую позицию с равной вероятностью. Если бы мы использовали обычную сортировку вставкой, мы бы получили вместо этого биномиальное распределение.
Обратите внимание, что этот алгоритм неэффективен в обоих режимах по сравнению со случайной сортировкой Фишера-Йейтса и сортировкой слиянием, поскольку вставка элемента в произвольную позицию является дорогой, если использование массива и бинарный поиск требуют линейного времени при использовании списка. Но, возможно, модификация сортировки кучи или сортировки дерева подобным образом может привести к более быстрому алгоритму.