2009-12-04 46 views
8

Đó là một vấn đề nổi tiếng với Quicksort khi tập dữ liệu nằm trong hoặc gần như theo thứ tự sắp xếp, hiệu suất giảm đáng kể. Trong trường hợp này, Sắp xếp chèn, thường rất chậm, có thể dễ dàng là lựa chọn tốt nhất. Câu hỏi đặt ra là biết khi nào nên sử dụng.Thuật toán phân tích trước khi phân loại?

Có sẵn thuật toán để chạy qua tập dữ liệu, áp dụng hệ số so sánh và trả về báo cáo về cách tập dữ liệu sắp xếp theo thứ tự sắp xếp không? Tôi thích Delphi/Pascal hơn, nhưng tôi có thể đọc các ngôn ngữ khác nếu ví dụ không quá phức tạp.

+1

Sự chậm chạp này với các trình tự sắp xếp trước chỉ là một vấn đề, AFAIK, nếu việc triển khai quá đơn giản đối với việc lựa chọn phần tử trục. Xem http://www.cprogramming.com/tutorial/computersciencetheory/quicksort.html ví dụ. – Dirk

Trả lời

9

Như bạn mong đợi khá nhiều suy nghĩ đi sâu vào vấn đề này. Kỹ thuật trung bình-ba có nghĩa là hành vi trường hợp xấu nhất của quicksort không xảy ra đối với dữ liệu được sắp xếp, mà thay vào đó là các trường hợp ít rõ ràng hơn.

Introsort khá thú vị, vì nó tránh trường hợp xấu nhất bậc hai của quicksort hoàn toàn. Thay vì câu hỏi tự nhiên của bạn, "làm thế nào để tôi phát hiện ra rằng dữ liệu được sắp xếp gần như", nó có hiệu lực yêu cầu chính nó như nó đi cùng, "này có phải mất quá lâu?". Nếu câu trả lời là có, nó chuyển từ quicksort sang heapsort.

Timsort kết hợp sắp xếp hợp nhất với sắp xếp chèn và thực hiện rất tốt trên dữ liệu được sắp xếp hoặc sắp xếp ngược và trên dữ liệu bao gồm các tập hợp con được sắp xếp hoặc sắp xếp ngược.

Vì vậy, có lẽ câu trả lời cho câu hỏi của bạn là "bạn không cần phân tích trước khi vượt qua, bạn cần một thuật toán sắp xếp thích ứng".

+0

+1 cho liên kết timsort –

+0

+1 wow, timsort trông khá gọn gàng. – wowest

0

Tôi chưa từng nghe về bất kỳ phân tích phân loại trước nào nhưng ý kiến ​​của tôi là nếu bạn đang đi qua tập dữ liệu để phân tích nó thì bạn đã cắt thành hiệu suất của thời gian phân loại tổng thể của bạn.

+2

Đó là một điểm tốt, nhưng nếu việc phân tích vượt qua là O (n), nó sẽ không thống trị thời gian phân loại tiệm cận. Và nếu nó có thể giúp tránh được thời gian phân loại trường hợp xấu nhất O (n^2), nó có thể là lợi ích ròng trong thời gian phân loại cho các tập dữ liệu lớn. – ddaa

+1

@ddaa: Điều đó đúng với các loại so sánh, nhưng có thể phân loại O (n) với Phân loại Radix hoặc Sắp xếp nhóm. Nếu chúng tôi bao gồm các thuật toán này, thời gian sắp xếp có thể bị chi phối bởi thời gian phân tích ... –

+1

@ Jason: Bạn sẽ không thực hiện phân tích này về dữ liệu mà bạn sắp sắp xếp. Câu hỏi đặt ra là lựa chọn giữa sắp xếp nhanh và sắp xếp, và bạn dự định làm không ... –

0

Một giải pháp có thể là lấy phần tử đầu tiên, cuối và phần tử giữa trong phạm vi sắp xếp hiện tại (trong thao tác QuickSort) và chọn phần giữa làm phần tử trục.

+0

Trường hợp tốt nhất của bạn vẫn là O (N log N), trong đó sắp xếp chèn là O (N) cho dữ liệu gần như được sắp xếp. – wowest

0

Để phân tích đầy đủ với mục đích quyết định sử dụng thuật toán nào, bạn sẽ thực hiện gần như công việc sắp xếp. Bạn có thể làm một cái gì đó như kiểm tra các giá trị tại một tỷ lệ phần trăm nhỏ ngẫu nhiên nhưng tăng chỉ số (tức là phân tích một mẫu nhỏ của các mặt hàng).

3

Cũng có SmoothSort, có vẻ khá khó thực hiện, nhưng nó khác nhau giữa O (N log N) đến O (N) tùy thuộc vào cách sắp xếp dữ liệu bắt đầu bằng.

http://en.wikipedia.org/wiki/Smoothsort

dài khéo léo PDF: http://www.cs.utexas.edu/users/EWD/ewd07xx/EWD796a.PDF

Tuy nhiên, nếu dữ liệu của bạn là thực sự rất lớn và bạn phải truy cập vào nó serially, mergesort có lẽ là tốt nhất. Nó luôn luôn là O (N log N) và nó có các thuộc tính 'locality' xuất sắc.

0

Bạn vẫn phải chạy qua tất cả các bản ghi để xác định xem đã được sắp xếp hay chưa, để cải thiện hiệu suất, bắt đầu với bản ghi đầu tiên của bạn và chạy phần còn lại cho đến khi bạn nhận thấy điều gì đó không được sắp xếp đúng hoặc đến cuối danh sách. Nếu bạn tìm thấy lỗi sau đó chỉ sắp xếp các mục từ vị trí đó đến cuối (kể từ khi bắt đầu danh sách đã được sắp xếp).

Tại mỗi mục trong phần thứ hai, xem mục có là < hơn phần tử cuối cùng trong phần đầu tiên và nếu có, hãy sử dụng sắp xếp chèn vào CHỈ phần đầu tiên. Nếu không, Quicksort sẽ chống lại tất cả các mục khác trong phần thứ hai. Bằng cách này, sắp xếp được tối ưu hóa cho trường hợp cụ thể.

0

Sắp xếp nhanh beng một vấn đề duy nhất khi tập dữ liệu là rất lớn và đã chủ yếu là sắp xếp, tôi sẽ sử dụng công nghệ tự động sau (khi chờ đợi một giải pháp toàn diện):

  • Đừng bận tâm nếu dữ liệu thiết lập kích thước là dưới ngưỡng.

  • Nếu bạn có quyền truy cập nhanh (được lập chỉ mục) vào bản ghi (mục) lấy mẫu có 1 bản ghi trong mỗi bản ghi N và xem chúng đã được sắp xếp chưa. Nên đủ nhanh cho một mẫu nhỏ và sau đó bạn có thể quyết định sử dụng sắp xếp nhanh hay không.

+0

nhưng mẫu bị lỗi nếu 1 bản ghi trong mỗi N được sắp xếp, nhưng bản ghi +1 trong mỗi N không phải là. bạn vẫn có thể phải đọc mọi bản ghi để xem liệu MỘT trong số chúng không được lấy mẫu không đúng thứ tự. – skamradt

+0

Đồng ý, nhưng có rất ít cơ hội thống kê rằng mẫu sẽ lệch rất nhiều so với tổng thể, đặc biệt nếu bạn ngẫu nhiên một chút N. –

0

Để tạo một điểm khái niệm mà mọi người chưa thực hiện: Quicksort là thuật toán phân chia và chinh phục thông thường với lỗi rõ ràng trong những trường hợp hiếm hoi. Giả sử bạn muốn sắp xếp một chồng giấy tờ sinh viên. (Mà tôi phải làm với một số quy luật.) Trong thuật toán quicksort, bạn chọn một số giấy, trục xoay. Sau đó chia các giấy tờ khác theo chúng cho dù trước hoặc sau trục xoay. Sau đó lặp lại điều đó với hai tập con. Lỗi là gì? Trục xoay có thể là một tên gần một đầu của danh sách thay vì ở giữa, để nó không hoàn thành nhiều để chia thành hai cọc.

Sắp xếp hợp nhất là một thuật toán phân chia và conquer khác hoạt động theo thứ tự khác. Bạn có thể hợp nhất hai danh sách được sắp xếp theo thời gian tuyến tính. Chia các bài báo thành hai đống bằng nhau hoặc gần như bằng nhau, sau đó phân loại đệ quy mỗi một, sau đó hợp nhất. Sắp xếp hợp nhất không có bất kỳ lỗi nào. Một lý do mà quicksort là phổ biến hơn so với sắp xếp hợp nhất là lịch sử: Quicksort nhanh (thường) và nó hoạt động mà không cần thêm bộ nhớ nào. Nhưng những ngày này, nó có thể quan trọng hơn để tiết kiệm so sánh hơn để tiết kiệm bộ nhớ, và sắp xếp lại thực tế thường được trừu tượng bằng cách cho phép con trỏ. Nếu mọi thứ luôn luôn như vậy, thì tôi nghi ngờ rằng sắp xếp hợp nhất sẽ đơn giản hơn phổ biến hơn quicksort. (Và có thể thêm "nhanh" vào tên là bán hàng tốt.)

+0

Từ POV của tôi, lợi ích của một loại tại chỗ không phải là quá nhiều mà nó tiết kiệm * bộ nhớ *, vì nó giúp tiết kiệm một cấp phát bộ nhớ và do đó không thể thất bại. Vì vậy, khi sắp xếp một mảng, sắp xếp quicksort/heapsort/insertion sort/bubble tất cả đều có giao diện người dùng đẹp hơn mergesort. Nếu mergesort được ưa thích để quicksort, thì tất nhiên bạn có thể cố gắng phân bổ bộ nhớ, và nếu nó không làm một quicksort thay thế. Nếu bạn đang phân bổ một mảng con trỏ thứ hai và phân loại đó, thì bạn đang giới thiệu khả năng thất bại ở đó, và do đó cũng có thể cho phép thất bại ở nơi khác. –

+0

@SteveJessop Đó là một điểm công bằng. Tuy nhiên, mối quan tâm đó, trong khi vẫn còn đáng kể trong một số trường hợp, cũng là một chút ngày. Tôi đồng ý rằng nó là không tầm thường đối với môi trường bên ngoài để phân bổ khá bộ nhớ cho mỗi chương trình khách hàng hoặc chức năng mà muốn nó. Tuy nhiên, ngay cả điều đó đã trở nên tốt hơn theo thời gian trong rất nhiều môi trường. –

+0

Tôi không nghĩ nó thực sự là một câu hỏi về sự công bằng, nhiều như những gì xảy ra khi bạn chạy ra ngoài, và liệu bạn có mạnh mẽ với điều đó không. Nếu phân bổ có thể thất bại thì bạn viết chương trình của bạn theo một cách. Nếu thay vào đó hệ điều hành thổi một cái gì đó ra khỏi nước cho đến khi nó có đủ bộ nhớ để đáp ứng yêu cầu hoặc lỗi trang trên truy cập đầu tiên, sau đó bạn viết chương trình của bạn theo cách khác. Một số ngôn ngữ có một con đường trung gian, trong đó trong lý thuyết bạn * có thể * bắt ngoại lệ bộ nhớ ngoài và tiếp tục, nhưng trong thực tế bạn không, bạn để cho ngoại lệ giết bạn. Tôi cho rằng đó có thể được coi là "up-to-date" cách để làm điều đó ;-) –

Các vấn đề liên quan