Poniższy algorytm deterministyczny (bez komparatora) działa dla krotki wejściowej :(za1, ... ,zan)
- Wykonaj tasowanie Fisher-Yates za pomocą komparatora z parą statyczną (powiedz ) jako rzut monetą (próbkowanie przy odrzucaniu-odrzucaniu). Jeśli komparator wyprowadza za pierwszym razem, użyj go odwróconego, aby uniknąć nieskończonej pętli odrzucania w przypadku deterministycznym.za1<za2)1
- (opcjonalne przyspieszenie: Wypróbuj pojedynczą parę razy, gdzie jest długością lub wartością wejściową. Jeśli dowolne dwa wyjścia różnią się, zwróć permutację uzyskaną w (1))nn
- Posortuj tablicę za pomocą sortowania scalającego.
Biorąc pod uwagę deterministyczną relację porządku jako komparator, ten algorytm sortuje tablicę w czasie ponieważ losowanie Fisher-Yates działa w przy użyciu maximal nielosowe „losowe bity” (np. wywołania do twojego komparatora) na każdym kroku i sortowanie według scalania ma tę samą asymptotyczną złożoność. Wynik (1) jest w tym przypadku całkowicie bezużyteczny, ale ponieważ następuje po nim prawdziwy rodzaj, nie szkodzi.O (nlogn )O (n)O (logn )
Biorąc pod uwagę prawdziwy rzut monetą, ponieważ komparator (1) permutuje tablicę z jednakowym prawdopodobieństwem dla każdej permutacji, a jeśli naprawdę musisz zrobić (3) (pominąłeś (2) lub (2) nie udało się ustalić losowości), to nie jest szkoda, ponieważ rozkład jego wyniku zależy tylko od kolejności jego wejścia, która jest równomiernie rozłożona między wszystkimi permutacjami z powodu (1), więc wynik całego algorytmu jest również równomiernie rozłożony. Liczba powtórzeń każdego próbkowania akceptacji-odrzucenia jest rozkładem geometrycznym (odrzucenie z prawdopodobieństwem ), a zatem ma wartość oczekiwaną . Każde powtórzenie wykorzystuje maksymalnie bitów, więc analiza czasu wykonywania jest prawie taka sama jak w przypadku deterministycznym, ale otrzymujemy tylko<12)< 2lognoczekiwany czas działania , z możliwością nieterminacji (kończy się prawie na pewno ).O (nlogn )
Jak wskazał Joe: Jeśli nie podoba ci się test dla pierwszego bitu w (1), zrób (3), a następnie (1) i użyj który zawsze wynosi , ponieważ tablica jest już posortowana w przypadku deterministycznym . Dodatkowo musisz odjąć swoją liczbę losową od górnej granicy zakresu w pętli, ponieważ górna granica liczby losowej daje identyczną permutację. Pamiętaj jednak, że (2) jest wtedy zabronione, ponieważ zawsze musisz wykonać losowanie w przypadku okupu.zan<za10
Możesz nawet użyć tych samych wywołań do komparatora dla (1) i (3), ale udowodnienie, że wynik jest równomiernie rozłożony, jest co najmniej o wiele trudniejsze, o ile w ogóle możliwe.
Poniższy algorytm nie ma odrębnych faz do losowego sortowania i sortowania, ale jest asymptotycznie wolniejszy. Jest to w zasadzie
sortowanie przez wstawianie z
wyszukiwaniem binarnym . Będzie używać do oznaczenia wejściowe i dla określenia rezultatu po -tym etap:
a = (za1, ... ,zan)bk= (bk , 1, ... ,bk , k)k
- Ustawb1 , 1=za1
- Jeśli to i inaczej i . W obu przypadkach będzie zawsze wynosić (tj. Fałsz) dla nielosowego komparatora.za2)<za1b2)= (za2),za1)( c , d) : = ( 2 , 1 )b2)= (za1,za2))( c , d) : = ( 1 , 2 )zare<zado0
- Aby uzyskać dla najpierw uzyskaj .bkk ≥ 3bk - 1
- Niech i , tzn. jest najmniejszą potęgą nie mniejszą niż .l = ⌈ l osol2)k ⌉k′=2)lk′2)k
- Niech . Dla każdego niech
ja0= 0j ∈ { 1 , … , l }
jajot=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪jaj - 1+2)l - jjaj - 1jaj - 1+2)l - jjaj - 1jaj - 1+2)l - j> k - 1 ∧zare<zadojaj - 1+2)l - j> k - 1 ∧ ¬ (zare<zado)jaj - 1+2)l - j≤ k - 1 ∧bk - 1 ,jaj - 1+2)l - j<zakjaj - 1+2)l - j≤ k - 1 ∧ ¬ (bk - 1 ,jaj - 1+2)l - j<zak)
- Jeśli powtórz (5.) elsejal> kbk= (bk - 1 , 1, ... ,bk - 1 ,jal- 1,zak,bk - 1 ,jal, ... ,bk - 1 , k - 1)
- Wyjściebn
Przypadek losowy: 5 + klauzula if z 6 jest w zasadzie próbką akceptacji-odrzucenia. Reszta algorytmu jest naiwnym tasowaniem: przetasuj pierwsze elementy i dodaj ty element do każdej pozycji z jednakowym prawdopodobieństwem. Gdybyśmy użyli normalnego sortowania wstawiania, otrzymalibyśmy zamiast tego rozkład dwumianowy.k - 1k
Zauważ, że ten algorytm jest nieefektywny w obu trybach w porównaniu do sortowania i łączenia przez Fisher-Yatesa, ponieważ wstawianie elementu do dowolnej pozycji jest kosztowne, jeśli użycie tablicy i wyszukiwanie binarne wymaga czasu liniowego, jeśli używasz listy. Ale być może modyfikacja sortowania sterty lub sortowania drzewa w podobny sposób może prowadzić do szybszego algorytmu.