Thuật toán xác định (không có bộ so sánh) sau đây hoạt động cho một bộ dữ liệu đầu vào :(a1,…,an)
- Thực hiện việc xáo trộn Fisher-Yates bằng cách sử dụng bộ so sánh của bạn với một số cặp tĩnh (giả sử ) dưới dạng lật đồng xu (thực hiện lấy mẫu từ chối chấp nhận). Nếu bộ so sánh xuất ra lần đầu tiên, hãy sử dụng nó đảo ngược để tránh vòng lặp từ chối vô tận trong trường hợp xác định. 1a1<a21
- (tăng tốc tùy chọn: Hãy thử một cặp lần, trong đó là độ dài hoặc đầu vào của bạn. Nếu hai đầu ra khác nhau sẽ trả về hoán vị thu được trong (1))nnn
- Sắp xếp mảng của bạn bằng cách sử dụng sắp xếp hợp nhất.
Đưa ra một mối quan hệ thứ tự xác định khi so sánh, thuật toán này sắp xếp một mảng theo thời gian kể từ khi shuffle Fisher-Yates chạy trong bằng cách sử dụng tối đa "bit ngẫu nhiên" không ngẫu nhiên (ví dụ như các cuộc gọi đến bộ so sánh của bạn) trong mỗi bước và sắp xếp hợp nhất có cùng độ phức tạp tiệm cận. Kết quả của (1) là hoàn toàn vô dụng trong trường hợp này, nhưng vì nó được theo sau bởi một loại thực sự, điều này không có hại.O ( n ) O ( log n )O(nlogn)O(n)O(logn)
Đưa ra một đồng xu thực sự khi bộ so sánh (1) hoán vị mảng với xác suất bằng nhau cho mỗi lần hoán vị và nếu bạn thực sự phải làm (3) (bạn bỏ qua (2) hoặc (2) không xác định được tính ngẫu nhiên), thì điều này là không tác hại vì phân phối kết quả của nó chỉ phụ thuộc vào thứ tự đầu vào được phân phối đồng đều giữa tất cả các hoán vị vì (1), do đó kết quả của toàn bộ thuật toán cũng được phân phối đồng đều. Số lần mỗi lần lấy mẫu từ chối chấp nhận phải được phân phối lại về mặt hình học (từ chối với xác suất ) và do đó, nó có giá trị mong đợi . Mỗi lần lặp lại sử dụng tối đa bit bit, vì vậy phân tích thời gian chạy gần giống như trong trường hợp xác định, nhưng chúng tôi chỉ nhận được một <2lognO(nlogn)<12<2lognthời gian chạy dự kiến của , với khả năng không bị hủy (chỉ chấm dứt gần như chắc chắn ).O(nlogn)
Như Joe đã chỉ ra: Nếu bạn không thích thử nghiệm cho bit đầu tiên trong (1), hãy làm (3) sau đó (1) và sử dụng luôn là , vì mảng đã được sắp xếp trong trường hợp xác định . Ngoài ra, bạn phải trừ số ngẫu nhiên của bạn khỏi giới hạn trên của phạm vi trong vòng lặp, bởi vì giới hạn trên cho số ngẫu nhiên mang lại hoán vị giống hệt nhau. Nhưng hãy lưu ý rằng (2) bị cấm sau đó, bởi vì bạn luôn phải thực hiện việc xáo trộn trong trường hợp tiền chuộc. 0an<a10
Bạn thậm chí có thể sử dụng cùng một cuộc gọi đến bộ so sánh của mình cho (1) và (3), nhưng sau đó chứng minh rằng kết quả được phân phối đồng đều ít nhất là khó hơn rất nhiều, nếu có thể.
Thuật toán sau đây không có các giai đoạn riêng biệt để xáo trộn và sắp xếp, nhưng chậm hơn về mặt triệu chứng. Về cơ bản,
đó là sắp xếp chèn với
tìm kiếm nhị phân . Tôi sẽ sử dụng để biểu thị đầu vào và để biểu thị kết quả sau vòng thứ :
a=(a1,…,an)bk=(bk,1,…,bk,k)k
- Đặtb1,1=a1
- Nếu thì và khác và . Trong cả hai trường hợp, sẽ luôn là (tức là sai) cho một bộ so sánh không ngẫu nhiên.a2<a1b2=(a2,a1)(c,d):=(2,1)b2=(a1,a2)(c,d):=(1,2)ad<ac0
- Để có được cho lấy .bkk≥3bk−1
- Đặt và , tức là là công suất nhỏ nhất bằng không nhỏ hơn .l=⌈log2k⌉k′=2lk′2k
- Đặt . Với mọi hãy để
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)
- Nếu lặp lại (5.) khácb k = ( b k - 1 , 1 , ... , b k - 1 , i l - 1 , một k , b k - 1 , i l , ... , b k - 1 , k - 1 )il>kbk=(bk−1,1,…,bk−1,il−1,ak,bk−1,il,…,bk−1,k−1)
- Đầu rabn
Trường hợp ngẫu nhiên: 5 + mệnh đề if của 6 về cơ bản là lấy mẫu từ chối chấp nhận. Phần còn lại của thuật toán là một shuffle ngây thơ: xáo trộn các phần tử đầu tiên và thêm phần tử thứ vào mỗi vị trí với xác suất bằng nhau. Nếu chúng ta sử dụng loại chèn thông thường, chúng ta sẽ có phân phối nhị thức thay thế.kk−1k
Lưu ý rằng thuật toán này không hiệu quả ở cả hai chế độ so với sắp xếp và hợp nhất Fisher-Yates vì việc chèn một phần tử vào một vị trí tùy ý là tốn kém nếu sử dụng một mảng và tìm kiếm nhị phân cần thời gian tuyến tính nếu sử dụng danh sách. Nhưng có lẽ việc sửa đổi sắp xếp heap hoặc sắp xếp cây theo cách tương tự có thể dẫn đến một thuật toán nhanh hơn.