Thuật toán sắp xếp nhanh nhất cho một mảng các số nguyên là gì?


55

Tôi đã bắt gặp nhiều thuật toán sắp xếp trong quá trình học trung học. Tuy nhiên, tôi không bao giờ biết cái nào là nhanh nhất (đối với một mảng số nguyên ngẫu nhiên). Vì vậy, câu hỏi của tôi là:

  • Đó là thuật toán sắp xếp nhanh nhất được biết đến hiện nay?
  • Về mặt lý thuyết, có thể có những cái còn nhanh hơn không? Vì vậy, những gì phức tạp nhất để sắp xếp?

7
"Nhanh" nghĩa là gì? Bạn muốn đo lường cái gì?
Raphael

2
"Mảng số nguyên ngẫu nhiên" nghĩa là gì? Ngẫu nhiên với phân phối gì? phân bố đồng đều? Gaussian? Tùy thuộc vào phân phối, có thể tốt hơn thuật toán thời gian chạy dự kiến. O(nlogn)
Bakuriu

@gen Hãy xem Radix sort. Việc thực hiện đúng có độ phức tạp O (n) cho Int32 chẳng hạn.
này


1
@gen: Xét về tiệm cận? Sau đó, thật dễ dàng: chọn bất kỳ thuật toán . Lưu ý rằng điều này có thể không liên quan gì đến hiệu suất trong thế giới thực (trung bình). Đây có thể là một giá trị đọc về vấn đề này. Θ ( n log n )ΘΘ(nlogn)
Raphael

Câu trả lời:


42

Nói chung, có các thuật toán sắp xếp , chẳng hạn như sắp xếp chèn, sắp xếp bong bóng và sắp xếp lựa chọn, mà bạn thường chỉ nên sử dụng trong các trường hợp đặc biệt; Quicksort, trường hợp xấu nhất nhưng thường là với các hằng số và thuộc tính tốt và có thể được sử dụng làm thủ tục sắp xếp mục đích chung; các thuật toán , như hợp nhất-sort và heap-sort, cũng là các thuật toán sắp xếp mục đích chung tốt; và hoặc thuật toán sắp xếp tuyến tính cho các danh sách các số nguyên, chẳng hạn như cơ số, xô và các loại đếm, có thể phù hợp tùy thuộc vào bản chất của các số nguyên trong danh sách của bạn.O ( n 2 ) O ( n log n ) O ( n log n ) O ( n )O(n2)O(n2)O(nlogn)O(nlogn)O(n)

Nếu các yếu tố trong danh sách của bạn sao cho tất cả những gì bạn biết về chúng là mối quan hệ tổng thứ tự giữa chúng, thì thuật toán sắp xếp tối ưu sẽ có độ phức tạp . Đây là một kết quả khá tuyệt vời và một kết quả mà bạn sẽ có thể dễ dàng tìm thấy chi tiết trực tuyến. Các thuật toán sắp xếp tuyến tính khai thác thêm thông tin về cấu trúc của các phần tử được sắp xếp, thay vì chỉ là mối quan hệ tổng thứ tự giữa các phần tử.Ω(nlogn)

Thậm chí, nói chung, tính tối ưu của thuật toán sắp xếp phụ thuộc rất nhiều vào các giả định mà bạn có thể đưa ra về loại danh sách bạn sẽ sắp xếp (cũng như mô hình máy mà thuật toán sẽ chạy, có thể khiến việc sắp xếp kém đi thuật toán là sự lựa chọn tốt nhất, xem xét sắp xếp bong bóng trên các máy có băng để lưu trữ). Giả định của bạn càng mạnh, thuật toán của bạn có thể cắt càng nhiều góc. Theo các giả định rất yếu về mức độ hiệu quả mà bạn có thể xác định "tính sắp xếp" của danh sách, độ phức tạp trong trường hợp xấu nhất tối ưu thậm chí có thể là .Ω(n!)

Câu trả lời này chỉ đề cập đến sự phức tạp. Thời gian chạy thực tế của việc triển khai các thuật toán sẽ phụ thuộc vào một số lượng lớn các yếu tố khó giải thích trong một câu trả lời duy nhất.


Tôi đoán một số nên là ? ΩOΩ
Raphael

1
@Raphael Meh. Tôi nghĩ rằng hầu hết trong số họ là dù sao đi nữa. Tôi cho rằng giới hạn dưới có lẽ được kết xuất tốt hơn . Tôi sẽ thay đổi một vài trong số chúng có ý nghĩa nhất. ΩΘΩ
Patrick87

7
Tôi bỏ phiếu @Raphael nhận được một chiếc mũ cảnh sát : PΩ
Realz Slaw

2
@RealzSlaw: Tôi sẽ mặc nó một cách tự hào. :]
Raphael

1
@gen Xem stackoverflow.com/a/3274203 để biết một số thảo luận. Về cơ bản, nếu các bản ghi riêng lẻ rất lớn và nó không được lưu trữ theo cách truy cập ngẫu nhiên và lượng dữ liệu phải được thực hiện tại chỗ, thì sắp xếp bong bóng là cách để đi. Những trường hợp này thường hiếm ngày nay, nhưng bạn vẫn có thể gặp chúng.
Patrick87

16

Câu trả lời, như thường thấy đối với những câu hỏi như vậy, là "nó phụ thuộc". Nó phụ thuộc vào những thứ như (a) số nguyên lớn đến mức nào, (b) liệu mảng đầu vào có chứa số nguyên theo thứ tự ngẫu nhiên hay theo thứ tự gần như sắp xếp hay không, (c) bạn có cần thuật toán sắp xếp ổn định hay không, cũng như các yếu tố khác, (d) liệu toàn bộ danh sách các số có phù hợp với bộ nhớ (sắp xếp trong bộ nhớ so với sắp xếp bên ngoài) và (e) máy bạn chạy trên đó không.

Trong thực tế, thuật toán sắp xếp trong thư viện chuẩn của ngôn ngữ của bạn có thể sẽ khá tốt (khá gần với tối ưu), nếu bạn cần một loại sắp xếp trong bộ nhớ. Do đó, trong thực tế, chỉ cần sử dụng bất kỳ chức năng sắp xếp nào được cung cấp bởi thư viện tiêu chuẩn và đo thời gian chạy. Chỉ khi bạn thấy rằng (i) sắp xếp là một phần lớn của tổng thời gian chạy và (ii) thời gian chạy là không thể chấp nhận được, bạn mới nên loay hoay với thuật toán sắp xếp. Nếu hai điều kiện đó được giữ, thì bạn có thể xem xét các khía cạnh cụ thể của miền cụ thể của bạn và thử nghiệm với các thuật toán sắp xếp nhanh khác.

Nhưng thực tế, trong thực tế, thuật toán sắp xếp hiếm khi là một nút cổ chai hiệu năng lớn.


9

Hơn nữa, trả lời câu hỏi thứ hai của bạn

Về mặt lý thuyết, có thể có những cái còn nhanh hơn không?
Vì vậy, những gì phức tạp nhất để sắp xếp?

Đối với sắp xếp mục đích chung, độ phức tạp của vấn đề sắp xếp dựa trên so sánh(n log n) . Có một số thuật toán thực hiện sắp xếp trong O (n), nhưng tất cả chúng đều dựa vào việc đưa ra các giả định về đầu vào và không phải là thuật toán sắp xếp mục đích chung.

Về cơ bản, độ phức tạp được đưa ra bởi số lượng so sánh tối thiểu cần thiết để sắp xếp mảng (log n đại diện cho chiều cao tối đa của cây quyết định nhị phân được xây dựng khi so sánh từng yếu tố của mảng).

Bạn có thể tìm thấy bằng chứng chính thức để sắp xếp độ phức tạp thấp hơn ràng buộc ở đây :


3
Câu trả lời này không hoàn toàn đúng. không phải là một phổ biến thấp hơn bị ràng buộc để phân loại. Giới hạn dưới đó chỉ áp dụng cho các loại dựa trên so sánh , tức là các thuật toán sắp xếp chỉ sử dụng so sánh. Một số thuật toán sắp xếp không dựa trên so sánh. Câu lệnh "Có một số thuật toán thực hiện sắp xếp trong O (n), nhưng tất cả chúng đều dựa vào việc đưa ra các giả định về đầu vào và không phải là thuật toán sắp xếp mục đích chung." có thể là một chút sai lệch - hãy cẩn thận. Radix-sort là một thuật toán sắp xếp mục đích chung (giả sử bạn đang sắp xếp các số nguyên có chiều rộng cố định). Ω(nlogn)
DW

Phụ thuộc vào những gì bạn có ý nghĩa của vấn đề sắp xếp . Các loại dựa trên so sánh mục đích chung không phải là loại vấn đề sắp xếp duy nhất mà mọi người gặp phải.
Patrick87

1
Điều đó đúng, tất nhiên. Tôi nên được cụ thể hơn, cảm ơn vì đã chỉ ra nó. Tuy nhiên, tôi hơi tò mò về cách tiếp cận sắp xếp khác (không dựa trên so sánh) mà bạn đang đề cập đến; Radix Sort chính xác là loại thuật toán O (n) mà tôi đã nói đến - bạn phải 'giả sử' một cái gì đó về đầu vào (số nguyên có chiều rộng cố định). Theo nghĩa này, nó không phải là một thuật toán sắp xếp mục đích chung, phải không?
rla4

1
@DW: Không nên coi sắp xếp Radix là thuật toán sắp xếp 'mục đích chung', vì nó yêu cầu các khóa số nguyên có độ dài cố định; nó không hữu ích nếu không Nhưng tôi nhận được quan điểm của bạn. :) Tôi đoán sai lầm của tôi là tập trung vào việc sắp xếp mọi thứ có thể so sánh, thay vì sắp xếp các số nguyên , cụ thể. Chúng là những vấn đề khác nhau, và có một bộ giải pháp khả thi khác nhau. Câu hỏi có đề cập đến "một mảng số nguyên ngẫu nhiên", nhưng tôi thừa nhận tôi đã lấy nó làm ví dụ, thay vì hạn chế.
rla4

2
@DavidR Richby, nhìn lại điều này sau một năm rưỡi, tôi đồng ý với bạn. Cảm ơn bạn.
DW

3

Thuật toán sắp xếp số nguyên nhanh nhất trong trường hợp xấu nhất mà tôi gặp phải là thuật toán của Andersson et al. Nó có trường hợp xấu nhất là , dĩ nhiên là nhanh hơn O ( n log n ) .O(nloglogn)O(nlogn)


2
Điều đó rất thú vị nhưng bạn cần cung cấp thêm thông tin. Kể từ khi bạn đề cập đến , tôi giả sử bạn biết rằng sắp xếp so sánh dựa trên các số nguyên chung provably đòi hỏi thời gian Ω ( n log n ) . Bất cứ điều gì nhanh hơn bất thường đều phải đưa ra các giả định về dữ liệu: ví dụ, sắp xếp cơ số chạy trong thời gian tuyến tính giả sử rằng mọi phần tử của mảng nhiều nhất là một hằng số. Trong những điều kiện nào thuật toán này sắp xếp trong O ( n log log n ) và nó thực hiện như thế nào trong thực tế đối với các thuật toán khác như quicksort và radix sort? nlognΩ(nlogn)O(nloglogn)
David Richerby

1

Tôi đã đọc qua hai câu trả lời khác tại thời điểm viết bài này và tôi không nghĩ ai trả lời câu hỏi của bạn một cách thích hợp. Các câu trả lời khác xem xét các ý tưởng không liên quan về phân phối ngẫu nhiên và độ phức tạp không gian có thể nằm ngoài phạm vi của các nghiên cứu trung học. Vì vậy, đây là mất của tôi.

An(n1)A(n1)Ω(n)O(n)Ω(viết sai rồi)

Ω(viết sai rồi)Ôi(viết sai rồi)viết sai rồi2viết sai rồi3viết sai rồi-51viết sai rồi2


Ôi(viết sai rồi)viết sai rồilgviết sai rồin232O(viết sai rồi)Ôi(viết sai rồilgviết sai rồi)(đối với quicksort hoặc mergesort), trong thực tế, việc so sánh không quá rõ ràng: các hằng số ẩn trong ký hiệu big-O trở nên rất quan trọng và hằng số cho radix-sort cao hơn hằng số cho quicksort hoặc mergesort.
DW

tôig(viết sai rồi)viết sai rồi

Ω(viết sai rồi)

2
Ôi(wviết sai rồi)www{0,Giáo dục,2w-1}đăng nhậpviết sai rồiviết sai rồiw= =đăng nhậpviết sai rồiviết sai rồiđăng nhậpviết sai rồi.
David Richerby

1

Ôi(viết sai rồitôiogtôiogviết sai rồi)
Ôi(viết sai rồitôiogtôiogBạn)Bạn

0

đăng nhập(viết sai rồi!)

Ω(viết sai rồi)


0

Vì bạn không đề cập đến bất kỳ hạn chế nào đối với phần cứng và cho rằng bạn đang tìm kiếm "nhanh nhất", tôi sẽ nói bạn nên chọn một trong những thuật toán sắp xếp song song dựa trên phần cứng có sẵn và loại đầu vào bạn có.

Về lý thuyết như quick_sortO(n log n). Với pbộ xử lý, lý tưởng là điều này sẽ xảy ra O(n/p log n)nếu chúng ta chạy song song.

Để trích dẫn Wikipedia: Độ phức tạp thời gian của ...

Sắp xếp song song tối ưu là O (log n)

Trong thực tế, đối với kích thước đầu vào lớn, sẽ không thể đạt được O(log n)do các vấn đề về khả năng mở rộng.

Đây là mã giả cho sắp xếp hợp nhất Parallel . Việc thực hiện merge()có thể giống như trong sắp xếp hợp nhất thông thường:

// Sort elements lo through hi (exclusive) of array A.
algorithm mergesort(A, lo, hi) is
    if lo+1 < hi then  // Two or more elements.
        mid = ⌊(lo + hi) / 2⌋
        fork mergesort(A, lo, mid)
        mergesort(A, mid, hi)
        join
        merge(A, lo, mid, hi)

Cũng thấy:


Ôi(viết sai rồi2)

@Evil Vâng. Quicksort không phù hợp để xử lý song song. Đó là một ví dụ. Những cái nên được sử dụng được liệt kê trong các liên kết được đưa ra.
Kashyap
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.