Khi nào mỗi thuật toán sắp xếp được sử dụng? [đóng cửa]


170

Các trường hợp sử dụng khi thuật toán sắp xếp cụ thể được ưa thích hơn các thuật toán khác - hợp nhất sắp xếp so với QuickSort so với heapsort so với 'intro sort', v.v?

Có hướng dẫn nào được đề xuất trong việc sử dụng chúng dựa trên kích thước, loại cấu trúc dữ liệu, bộ nhớ và bộ đệm có sẵn và hiệu suất của CPU không?


Có thể tìm thấy một tập hợp các hình ảnh động cho các loại dữ liệu và thuật toán khác nhau tại <a href=" sorting-alerskyms.com/"> sorting-alerskyms.com </ a >
Chip Uni

2
Một hướng dẫn như bigochcoateet.com cho công cụ này sẽ là greaaaat
K - Độc tính trong SO đang phát triển.

@ChipUni ở đây là liên kết cố định: toptal.com/developers/sorting-alacticms
eric

2
Tại sao câu hỏi này bị đóng cửa!?
Arvand

Câu trả lời:


316

Đầu tiên, một định nghĩa, vì nó khá quan trọng: Một loại ổn định là một thứ được đảm bảo không sắp xếp lại các phần tử với các khóa giống hệt nhau.

Khuyến nghị:

Sắp xếp nhanh: Khi bạn không cần một loại ổn định và hiệu suất trường hợp trung bình quan trọng hơn hiệu suất trường hợp xấu nhất. Một loại nhanh chóng là trung bình O (N log N), O (N ^ 2) trong trường hợp xấu nhất. Việc triển khai tốt sử dụng bộ lưu trữ phụ O (log N) dưới dạng không gian ngăn xếp để đệ quy.

Hợp nhất sắp xếp: Khi bạn cần một sắp xếp ổn định, O (N log N), đây là về tùy chọn duy nhất của bạn. Nhược điểm duy nhất của nó là nó sử dụng không gian phụ O (N) và có hằng số lớn hơn một chút so với sắp xếp nhanh. Có một số loại hợp nhất tại chỗ, nhưng AFAIK chúng đều không ổn định hoặc tệ hơn O (N log N). Ngay cả các loại O (N log N) tại chỗ có hằng số lớn hơn nhiều so với loại hợp nhất cũ đơn giản đến mức chúng gây tò mò về mặt lý thuyết hơn là các thuật toán hữu ích.

Sắp xếp heap: Khi bạn không cần một loại ổn định và bạn quan tâm nhiều hơn đến hiệu suất trường hợp xấu nhất so với hiệu suất trường hợp trung bình. Nó được đảm bảo là O (N log N) và sử dụng không gian phụ O (1), nghĩa là bạn sẽ không bất ngờ hết dung lượng heap hoặc stack trên các đầu vào rất lớn.

Introsort: Đây là một loại nhanh chóng chuyển sang một loại heap sau một độ sâu đệ quy nhất định để giải quyết trường hợp xấu nhất O (N ^ 2) sắp xếp nhanh chóng. Nó hầu như luôn luôn tốt hơn một loại nhanh cũ đơn giản, vì bạn có được trường hợp trung bình của một loại nhanh, với hiệu suất O (N log N) được đảm bảo. Có lẽ lý do duy nhất để sử dụng một loại heap thay vì điều này là trong các hệ thống bị hạn chế bộ nhớ nghiêm trọng trong đó không gian ngăn xếp O (log N) thực sự có ý nghĩa.

Sắp xếp chèn : Khi N được đảm bảo nhỏ, bao gồm cả trường hợp cơ sở của sắp xếp nhanh hoặc sắp xếp hợp nhất. Trong khi đây là O (N ^ 2), nó có hằng số rất nhỏ và là một loại ổn định.

Sắp xếp bong bóng, sắp xếp lựa chọn : Khi bạn đang làm gì đó nhanh và bẩn và vì một số lý do, bạn không thể chỉ sử dụng thuật toán sắp xếp của thư viện chuẩn. Ưu điểm duy nhất này có hơn loại sắp xếp chèn là dễ thực hiện hơn một chút.


Các loại không so sánh: Trong một số điều kiện khá hạn chế, có thể phá vỡ rào cản O (N log N) và sắp xếp theo O (N). Dưới đây là một số trường hợp đáng để thử:

Đếm sắp xếp: Khi bạn sắp xếp các số nguyên với phạm vi giới hạn.

Sắp xếp cơ số: Khi log (N) lớn hơn đáng kể so với K, trong đó K là số chữ số cơ số.

Sắp xếp nhóm: Khi bạn có thể đảm bảo rằng đầu vào của bạn được phân phối đồng đều.


1
Như tôi nhớ lại, heap sort cũng có thời gian chạy rất dễ đoán ở chỗ có rất ít sự thay đổi giữa các đầu vào khác nhau có cùng kích thước, nhưng điều đó ít được quan tâm hơn so với không gian liên tục của nó. Tôi cũng thấy sắp xếp chèn là cách dễ nhất để thực hiện trong số 2 loại, nhưng có lẽ đó chỉ là tôi. Cuối cùng, bạn cũng có thể muốn đề cập đến Shell sort, việc này gần như đơn giản để thực hiện như sắp xếp chèn nhưng có hiệu suất tốt hơn, mặc dù vẫn không phải là log n.
JaakkoK

29
Đừng quên Bogosort ! ;-)
Alex Brasetvik

2
+1 Rất thú vị. Bạn có quan tâm để giải thích làm thế nào bạn có thể "đảm bảo ... phân phối đồng đều." cho sắp xếp nhóm?
Sam Overton

2
Tại sao introsort sẽ chậm hơn đáng kể so với sắp xếp nhanh chóng? Chi phí duy nhất là tính độ sâu đệ quy, không đáng kể. Nó chỉ chuyển đổi sau khi đệ quy sâu hơn nhiều so với trường hợp sắp xếp nhanh chóng tốt.
dsimcha

2
Bạn không đề cập đến trường hợp tốt nhất của loại bong bóng là O (n)!
Tara

33

Quicksort thường là nhanh nhất trung bình, nhưng nó có một số hành vi trường hợp xấu nhất khá khó chịu. Vì vậy, nếu bạn phải đảm bảo không có dữ liệu xấu nào cung cấp cho bạn O(N^2), bạn nên tránh nó.

Hợp nhất sắp xếp sử dụng bộ nhớ bổ sung, nhưng đặc biệt phù hợp để sắp xếp bên ngoài (nghĩa là các tệp lớn không phù hợp với bộ nhớ).

Heap-sort có thể sắp xếp tại chỗ và không có hành vi bậc hai trong trường hợp xấu nhất, nhưng trung bình thì chậm hơn quicksort trong hầu hết các trường hợp.

Khi chỉ có các số nguyên trong phạm vi bị hạn chế, bạn có thể sử dụng một số loại sắp xếp cơ số để làm cho nó rất nhanh.

Trong 99% trường hợp, bạn sẽ ổn với các loại thư viện, thường dựa trên quicksort.


6
+1: Đối với "Trong 99% trường hợp, bạn sẽ ổn với các loại thư viện, thường dựa trên quicksort".
Jim G.

Xoay vòng ngẫu nhiên giúp Quicksort có thời gian chạy O (nlogn) cho tất cả các mục đích thực tế, mà không cần bất kỳ đảm bảo nào về dữ liệu xấu. Tôi thực sự không nghĩ rằng bất cứ ai thực hiện một quicksort O (n ^ 2) cho bất kỳ mã sản xuất nào.
MAK

2
MAK, ngoại trừ, nói, thư viện tiêu chuẩn C qsort? ( Google.com/codesearch/... ) - khi mà hầu hết các loại "mã sản xuất" dựa
Eli Bendersky

Sắp xếp thư viện theo cách thông thường không dựa trên quicksort, vì nó không ổn định. Hầu như tất cả các ngôn ngữ cao hơn (mong đợi cho C) cung cấp một loại ổn định. Trong hầu hết các trường hợp tôi biết bạn cần một sự ổn định, hoặc ít nhất là một sự xác định, sắp xếp.
12431234123412341234123


3

Điều mà các liên kết được cung cấp để so sánh / hình ảnh động không xem xét là khi lượng dữ liệu vượt quá bộ nhớ khả dụng --- tại thời điểm đó, số lượng vượt qua dữ liệu, tức là chi phí I / O, chi phối thời gian chạy. Nếu bạn cần làm điều đó, hãy đọc phần "sắp xếp bên ngoài" thường bao gồm các biến thể của các loại hợp nhất và heap.

http://corte.si/posts/code/visualisingsorting/index.htmlhttp://corte.si/posts/code/timsort/index.html cũng có một số hình ảnh thú vị so sánh các thuật toán sắp xếp khác nhau.


0

@dsimcha đã viết: Đếm sắp xếp: Khi bạn sắp xếp các số nguyên với phạm vi giới hạn

Tôi sẽ thay đổi điều đó thành:

Sắp xếp đếm: Khi bạn sắp xếp các số nguyên dương (0 - Integer.MAX_VALUE-2 do chuồng bồ câu).

Bạn luôn có thể nhận được các giá trị tối đa và tối thiểu như là một heuristic hiệu quả trong thời gian tuyến tính.
Ngoài ra, bạn cần ít nhất n không gian thêm cho mảng trung gian và nó ổn định rõ ràng.

/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

(mặc dù nó thực sự sẽ cho phép MAX_VALUE-2) xem: Các mảng Java có kích thước tối đa không?

Ngoài ra tôi sẽ giải thích rằng độ phức tạp sắp xếp cơ số là O (wn) cho n khóa là số nguyên của kích thước từ w. Đôi khi w được trình bày dưới dạng hằng số, điều này sẽ giúp sắp xếp cơ số tốt hơn (với n đủ lớn) so với các thuật toán sắp xếp dựa trên so sánh tốt nhất, tất cả đều thực hiện so sánh O (n log n) để sắp xếp các khóa n. Tuy nhiên, nói chung w không thể được coi là một hằng số: nếu tất cả các khóa n là khác nhau, thì ít nhất w phải đăng nhập n để một máy truy cập ngẫu nhiên có thể lưu trữ chúng trong bộ nhớ, điều này mang lại độ phức tạp cao nhất cho O (n log n). (từ wikipedia)

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.