Thuật toán sắp xếp nào hoạt động tốt nhất trên hầu hết các dữ liệu được sắp xếp? [đóng cửa]


174

Thuật toán sắp xếp nào hoạt động tốt nhất trên hầu hết các dữ liệu được sắp xếp?


Đoán từ thiếu ngữ cảnh - bạn đang hỏi về một loại trong bộ nhớ mà không có yêu cầu để đổ kết quả trung gian vào đĩa?
Jonathan Leffler

1
Theo những hình ảnh động này, sắp xếp chèn hoạt động tốt nhất trên hầu hết các dữ liệu được sắp xếp.
dopple

Câu trả lời:


259

Dựa trên phương pháp rất khoa học để xem các gif hoạt hình, tôi sẽ nói các loại Chèn và Bong bóng là những ứng cử viên sáng giá.


19
đó là một liên kết tuyệt vời bằng cách này, thanh danh và 1
ninesided

5
Sắp xếp bong bóng là khủng khiếp. Nó luôn luôn là O (n ^ 2). Ít nhất hãy đưa ra câu trả lời của bạn cho nó là đúng xin vui lòng.
jjnguy

79
jjnguy, đó chỉ là sai. Tôi nghĩ rằng bạn cần phải học lại lớp thuật toán của bạn. Trên dữ liệu gần như được sắp xếp (trường hợp thích ứng), đó là O (N). Tuy nhiên, phải mất 2 lần chuyển qua dữ liệu và Chèn chỉ mất 1 cho dữ liệu gần như được sắp xếp, điều này làm cho Chèn là người chiến thắng. Bong bóng vẫn tốt mặc dù
mmcdole

3
Hiệu suất suy giảm thực sự tồi tệ nếu dữ liệu của bạn gần như không được sắp xếp. Tôi vẫn sẽ không sử dụng nó, cá nhân.
Blorgbeard ra khỏi

5
Liên kết đó đã bị hỏng khi tôi thử nó. Thay vào đó, hãy thử điều này: sorting-alerskyms.com
Michael La Voie

107

Chỉ một vài mặt hàng => SẮC XÁC NHẬN

Các mục hầu hết đã được sắp xếp => SẮC XÁC NHẬN

Quan tâm đến các tình huống xấu nhất => HEAP SORT

Quan tâm đến kết quả trung bình tốt => NHANH CHÓNG

Các vật phẩm được rút ra từ một vũ trụ dày đặc => BucksET SORT

Mong muốn viết càng ít mã càng tốt => SẮC XÁC NHẬN


1
Đó chính xác là loại câu trả lời tôi đang tìm kiếm, tôi đọc sách nhưng dường như tôi không tìm thấy bất kỳ lời giải thích rõ ràng nào cho việc lựa chọn thuật ngữ trong các trường hợp cụ thể, bạn có thể vui lòng giải thích điều này hoặc chuyển một liên kết để tôi có thể đưa vào nhiều hơn một chút? Cảm ơn
Simran kaur

9
Bạn nên thêm "Dữ liệu đã được sắp xếp theo tiêu chí khác => MERGE SORT"
Jim Hunziker

30

thời gian

Timsort là "sự hợp nhất tự nhiên, ổn định, tự nhiên" với " hiệu suất siêu nhiên trên nhiều loại mảng được đặt hàng một phần (ít hơn so với lg (N!), Và chỉ bằng N-1)". Python tích hợp sẵnsort()đã sử dụng thuật toán này một thời gian, rõ ràng có kết quả tốt. Nó được thiết kế đặc biệt để phát hiện và tận dụng các chuỗi được sắp xếp một phần trong đầu vào, thường xảy ra trong các bộ dữ liệu thực. Thông thường trong thế giới thực, việc so sánh đắt hơn nhiều so với việc hoán đổi các mục trong danh sách, vì người ta thường chỉ trao đổi con trỏ, điều này thường khiến cho bộ đếm thời gian là một lựa chọn tuyệt vời. Tuy nhiên, nếu bạn biết rằng các phép so sánh của bạn luôn rất rẻ (ví dụ, viết chương trình đồ chơi để sắp xếp các số nguyên 32 bit), các thuật toán khác tồn tại có khả năng hoạt động tốt hơn. Cách dễ nhất để tận dụng timsort tất nhiên là sử dụng Python, nhưng vì Python là nguồn mở nên bạn cũng có thể mượn mã. Thay phiên, mô tả ở trên chứa quá nhiều chi tiết để viết triển khai của riêng bạn.


16
log (n!) là (n * log (n)) do đó nó không phải là "siêu nhiên".
jfs

Đây là triển khai Java sắp có trong JDK7: cr.openjdk.java.net/~martin/webrevs/openjdk7/timsort/raw_files/
Tim

log (n!) không nhanh wolframalpha.com/input/?i=plot[log(N!) , {N, 0,1000}]
Behrooz

9
@JF Sebastian: timsort nhanh hơn nhiều lg(n!)so với so sánh trên một mảng gần như được sắp xếp, tất cả đều đi xuống O(n)! | @behrooz: Không có loại so sánh nào có thể có trường hợp trung bình tốt hơnO(n log n) , và lg(n!)O(n log n). Vì vậy, trường hợp xấu nhất của timsort là không có triệu chứng không tệ hơn bất kỳ loại so sánh nào khác. Hơn nữa, trường hợp tốt nhất của nó là tốt hơn hoặc bằng bất kỳ loại so sánh nào khác.
Artelius

3
Timsort vẫn là O (nlogn) trong trường hợp xấu nhất, nhưng trường hợp tốt của nó khá dễ chịu. Đây là một so sánh, với một số biểu đồ: stromberg.dnsalias.org/~strombrg/sort-comparison Lưu ý rằng bộ đếm thời gian trong Cython không nhanh bằng tốc độ của Python trong C.
user1277476

19

Sắp xếp chèn với hành vi sau:

  1. Đối với mỗi yếu tố ktrong các khe 1..n, trước tiên hãy kiểm tra xem el[k] >= el[k-1]. Nếu vậy, đi đến yếu tố tiếp theo. (Rõ ràng bỏ qua yếu tố đầu tiên.)
  2. Nếu không, sử dụng tìm kiếm nhị phân trong các phần tử 1..k-1để xác định vị trí chèn, sau đó di chuyển các phần tử qua. (Bạn chỉ có thể làm điều này nếu giá trị ngưỡng k>Tở đâu đó T; với mức nhỏ knày là quá mức cần thiết.)

Phương pháp này làm cho số lượng so sánh ít nhất.


Tôi nghĩ rằng sắp xếp bong bóng có thể đánh bại điều này nếu số lượng phần tử chưa được sắp xếp là rất nhỏ (như, một hoặc hai), nhưng nói chung điều này đánh vào tôi có lẽ là giải pháp tốt nhất.
Sol

Do bước 1, đối với bất kỳ yếu tố nào đã được sắp xếp, có chính xác một bước so sánh và không di chuyển dữ liệu, đó rõ ràng là điều tốt nhất bạn có thể làm. Bước 2 là bước bạn có thể cải thiện, nhưng bong bóng sẽ di chuyển cùng số lượng phần tử và có thể có nhiều so sánh hơn, tùy thuộc vào hàm ý của bạn.
Jason Cohen

Trên thực tế, về suy nghĩ xa hơn tôi nghĩ rằng sắp xếp bong bóng mạnh hơn tôi nghĩ. Đây thực sự là một câu hỏi khá khó. Chẳng hạn, nếu bạn chọn trường hợp danh sách được sắp xếp hoàn toàn ngoại trừ phần tử cuối cùng là đầu tiên, thì sắp xếp bong bóng sẽ vượt xa những gì bạn mô tả.
Sol

Tôi đã cố gắng thực hiện điều này nhưng tìm kiếm nhị phân không có nhiều cải tiến vì bạn vẫn phải di chuyển toàn bộ khối để chèn phần tử. Vì vậy, thay vì 2xrange bạn nhận được phạm vi + logb (phạm vi).
này

11

Hãy thử sắp xếp nội tâm. http://en.wikipedia.org/wiki/Introsort

Nó dựa trên quicksort, nhưng nó tránh được trường hợp xấu nhất mà quicksort có đối với các danh sách gần như được sắp xếp.

Thủ thuật là thuật toán sắp xếp này phát hiện các trường hợp quicksort chuyển sang chế độ trong trường hợp xấu nhất và chuyển sang sắp xếp heap hoặc hợp nhất. Các phân vùng gần được sắp xếp được phát hiện bởi một số phương pháp phân vùng không ngây thơ và các phân vùng nhỏ được xử lý bằng cách sử dụng sắp xếp chèn.

Bạn nhận được tốt nhất của tất cả các thuật toán sắp xếp chính cho chi phí của một mã nhiều hơn và phức tạp hơn.Và bạn có thể chắc chắn rằng bạn sẽ không bao giờ gặp phải trường hợp xấu nhất cho dù dữ liệu của bạn trông như thế nào.

Nếu bạn là lập trình viên C ++, hãy kiểm tra thuật toán std :: sort của bạn. Nó có thể đã sử dụng sắp xếp nội tâm.


7

Splaysort là một phương pháp sắp xếp tối nghĩa dựa trên cây splay , một loại cây nhị phân thích ứng. Splaysort không chỉ tốt cho dữ liệu được sắp xếp một phần, mà còn là dữ liệu được sắp xếp ngược một phần hoặc thực sự là bất kỳ dữ liệu nào có bất kỳ loại đơn đặt hàng nào trước đó. Đó là O (nlogn) trong trường hợp chung và O (n) trong trường hợp dữ liệu được sắp xếp theo một cách nào đó (chuyển tiếp, đảo ngược, ống nội tạng, v.v.).

Ưu điểm lớn của nó so với sắp xếp chèn là nó không hoàn nguyên về hành vi O (n ^ 2) khi dữ liệu hoàn toàn không được sắp xếp, vì vậy bạn không cần phải chắc chắn rằng dữ liệu được sắp xếp một phần trước khi sử dụng .

Nhược điểm của nó là không gian bên trên của cấu trúc cây splay mà nó cần, cũng như thời gian cần thiết để xây dựng và phá hủy cây splay. Nhưng tùy thuộc vào kích thước của dữ liệu và số lượng sắp xếp trước mà bạn mong đợi, chi phí có thể xứng đáng để tăng tốc độ.

Một bài báo về splaysort đã được xuất bản trong Phần mềm - Thực hành & Kinh nghiệm.



5

Smoothsort của Dijkstra là một loại tuyệt vời trên dữ liệu đã được sắp xếp. Đây là một biến thể heapsort chạy trong trường hợp xấu nhất O (n lg n) và trường hợp tốt nhất O (n). Tôi đã viết một phân tích về thuật toán, trong trường hợp bạn tò mò về cách thức hoạt động của nó.

Hợp nhất tự nhiên là một cách khác thực sự tốt cho điều này - đó là một biến thể hợp nhất từ ​​dưới lên, hoạt động bằng cách coi đầu vào là nối của nhiều phạm vi được sắp xếp khác nhau, sau đó sử dụng thuật toán hợp nhất để nối chúng lại với nhau. Bạn lặp lại quá trình này cho đến khi tất cả các phạm vi đầu vào được sắp xếp. Điều này chạy trong thời gian O (n) nếu dữ liệu đã được sắp xếp và trường hợp xấu nhất O (n lg n). Nó rất thanh lịch, mặc dù trong thực tế, nó không tốt như một số loại thích nghi khác như Timsort hay smoothsort.


các hằng số thời gian chạy của smoothsort so với các thuật toán sắp xếp khác là gì? (tức là thời gian chạy (smoothsort) / runtime (insertionsort) cho cùng một dữ liệu)
Arne Babenhauserheide

4

Nếu các phần tử đã được sắp xếp hoặc chỉ có một vài phần tử, đó sẽ là trường hợp sử dụng hoàn hảo cho Sắp xếp chèn!


3

Sắp xếp chèn mất thời gian O (n + số lượng đảo ngược).

Một đảo ngược là một cặp (i, j)như vậy i < j && a[i] > a[j]. Đó là, một cặp không theo thứ tự.

Một biện pháp "gần như được sắp xếp" là số lần đảo ngược --- người ta có thể lấy "dữ liệu gần như đã sắp xếp" để có nghĩa là dữ liệu có vài lần đảo. Nếu ai đó biết số lượng nghịch đảo là tuyến tính (ví dụ: bạn vừa thêm các phần tử O (1) vào danh sách đã sắp xếp), sắp xếp chèn sẽ mất thời gian O (n).


2

Như mọi người khác đã nói, hãy cẩn thận với Quicksort ngây thơ - có thể có hiệu suất O (N ^ 2) trên dữ liệu được sắp xếp hoặc gần như sắp xếp. Tuy nhiên, với một thuật toán thích hợp để lựa chọn trục (có thể là ngẫu nhiên hoặc trung bình của ba - xem phần Chọn Xoay cho Quicksort ), Quicksort vẫn sẽ hoạt động bình thường.

Nói chung, khó khăn trong việc lựa chọn các thuật toán như sắp xếp chèn là quyết định khi nào dữ liệu không đủ thứ tự mà Quicksort thực sự sẽ nhanh hơn.


2

Tôi sẽ không giả vờ có tất cả các câu trả lời ở đây, bởi vì tôi nghĩ rằng để có được câu trả lời thực tế có thể yêu cầu mã hóa các thuật toán và cấu hình chúng theo các mẫu dữ liệu đại diện. Nhưng tôi đã suy nghĩ về câu hỏi này suốt buổi tối, và đây là những gì xảy ra với tôi cho đến nay, và một số dự đoán về những gì hoạt động tốt nhất ở đâu.

Gọi N là tổng số mục, M là số thứ tự.

Sắp xếp bong bóng sẽ phải làm một cái gì đó như 2 * M + 1 đi qua tất cả N vật phẩm. Nếu M rất nhỏ (0, 1, 2?), Tôi nghĩ rằng điều này sẽ rất khó để đánh bại.

Nếu M nhỏ (ít hơn log N), sắp xếp chèn sẽ có hiệu suất trung bình tuyệt vời. Tuy nhiên, trừ khi có một mẹo mà tôi không thấy, nó sẽ có hiệu suất trường hợp xấu nhất. (Phải không? Nếu mục cuối cùng theo thứ tự xuất hiện trước, thì bạn phải chèn từng mục duy nhất, theo như tôi có thể thấy, điều này sẽ giết chết hiệu suất.) Tôi đoán có một thuật toán sắp xếp đáng tin cậy hơn cho việc này trường hợp, nhưng tôi không biết nó là gì.

Nếu M lớn hơn (bằng hoặc lớn hơn log N), sắp xếp nội tâm gần như chắc chắn là tốt nhất.

Ngoại lệ cho tất cả những điều đó: Nếu bạn thực sự biết trước các yếu tố nào chưa được sắp xếp, thì cách tốt nhất của bạn sẽ là kéo các mục đó ra, sắp xếp chúng bằng cách sử dụng sắp xếp nội tâm và hợp nhất hai danh sách được sắp xếp thành một danh sách được sắp xếp. Nếu bạn có thể nhanh chóng tìm ra những mặt hàng không theo thứ tự, đây cũng sẽ là một giải pháp chung tốt - nhưng tôi đã không thể tìm ra một cách đơn giản để làm điều này.

Suy nghĩ thêm (qua đêm): Nếu M + 1 <N / M, thì bạn có thể quét danh sách đang tìm kiếm một N / M liên tiếp được sắp xếp, sau đó mở rộng chạy theo hướng đó để tìm ra ngoài Sắp xếp các mặt hàng. Điều đó sẽ mất nhiều nhất so sánh 2N. Sau đó, bạn có thể sắp xếp các mục chưa sắp xếp và thực hiện hợp nhất được sắp xếp trên hai danh sách. Tổng số so sánh nên ít hơn một cái gì đó như 4N + M log2 (M), sẽ đánh bại bất kỳ thói quen sắp xếp không chuyên biệt nào, tôi nghĩ. (Thậm chí còn nghĩ thêm: điều này khó hơn tôi nghĩ, nhưng tôi vẫn nghĩ nó hợp lý có thể.)

Một cách giải thích khác của câu hỏi là có thể có nhiều mặt hàng không theo thứ tự, nhưng chúng rất gần với nơi chúng nên có trong danh sách. (Hãy tưởng tượng bắt đầu với một danh sách được sắp xếp và hoán đổi mọi vật phẩm khác với danh sách đi sau nó.) Trong trường hợp đó tôi nghĩ rằng sắp xếp bong bóng hoạt động rất tốt - Tôi nghĩ rằng số lần chuyền sẽ tỷ lệ thuận với vị trí xa nhất của một vật phẩm Là. Sắp xếp chèn sẽ hoạt động kém, bởi vì mỗi mục ngoài thứ tự sẽ kích hoạt chèn. Tôi nghi ngờ sắp xếp nội tâm hoặc một cái gì đó như thế cũng sẽ hoạt động tốt.


1

Nếu bạn đang cần triển khai cụ thể để sắp xếp các thuật toán, cấu trúc dữ liệu hoặc bất cứ thứ gì có liên kết đến ở trên, tôi có thể giới thiệu cho bạn dự án "Cấu trúc dữ liệu và thuật toán" tuyệt vời trên CodePlex không?

Nó sẽ có mọi thứ bạn cần mà không cần phát minh lại bánh xe.

Chỉ là hạt muối nhỏ của tôi.


1

Bộ sưu tập tốt đẹp các thuật toán sắp xếp cho mục đích này trong các câu trả lời, dường như thiếu Gnome Sort , cũng sẽ phù hợp và có lẽ cần ít nỗ lực thực hiện nhất.


0

Sắp xếp chèn là trường hợp tốt nhất O (n) trên đầu vào được sắp xếp. Và nó rất gần với đầu vào được sắp xếp chủ yếu (tốt hơn là sắp xếp nhanh).


0

suy ngẫm Hãy thử Heap. Tôi tin rằng nó phù hợp nhất trong các loại O (n lg n).


Tính nhất quán không phải là mối quan tâm ở đây. Heapsort sẽ cung cấp cho O (n lg n) ngay cả trên dữ liệu được sắp xếp và không thực sự thích ứng. Các tùy chọn khả thi có thể là: Sắp xếp chèn, Timsort và Bubbledort.
Tối đa

0

Sắp xếp bong bóng (hoặc, an toàn hơn, sắp xếp bong bóng hai hướng) có thể lý tưởng cho các danh sách được sắp xếp chủ yếu, mặc dù tôi đặt cược một loại sắp xếp được điều chỉnh (với kích thước khoảng cách ban đầu thấp hơn nhiều) sẽ nhanh hơn một chút khi danh sách không ' t khá hoàn hảo như được sắp xếp. Kết hợp sắp xếp xuống cấp để sắp xếp bong bóng.


0

tốt, nó phụ thuộc vào trường hợp sử dụng. Nếu bạn biết những yếu tố nào được thay đổi, loại bỏ và chèn sẽ là trường hợp tốt nhất theo như tôi nghĩ.


1
Thử nghiệm "theo như tôi quan tâm" về hiệu quả thuật toán đã làm sáng lên ngày của tôi :) Tuy nhiên, nghiêm túc, khi viết "loại bỏ và chèn", bạn có nghĩa là Sắp xếp chèn (đã được đề cập trong các câu trả lời trước), hoặc bạn có đề nghị một loại thuật toán mới? Nếu vậy, xin vui lòng mở rộng câu trả lời của bạn.
yoniLavi

0

Sắp xếp bong bóng chắc chắn là người chiến thắng Người tiếp theo trên radar sẽ là sắp xếp chèn.


4
gửi câu trả lời của bạn với một lời giải thích;

1
Tôi sẽ đề nghị bạn xem xét các câu trả lời có sẵn trước khi đăng để tránh trùng lặp.
angainor

-1

Tránh xa QuickSort - nó rất không hiệu quả đối với dữ liệu được sắp xếp trước. Sắp xếp chèn xử lý gần như sắp xếp dữ liệu tốt bằng cách di chuyển càng ít giá trị càng tốt.


-1 Mỗi triển khai công nghiệp của Quicksort đều có lựa chọn trục hợp lý
Stephan Eggermont

1
Có, nhưng không có lựa chọn trục nào là hoàn hảo trừ khi nó đắt tiền.
dùng1277476
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.