2011-11-29 32 views
22

Nhiều thuật toán hoạt động bằng cách sử dụng merge algorithm để hợp nhất hai mảng được sắp xếp khác nhau thành một mảng được sắp xếp duy nhất. Ví dụ, cho là đầu vào các mảngThuật toán kết hợp bộ nhớ thích ứng với bộ nhớ?

1 3 4 5 8 

2 6 7 9 

Các hợp nhất của các mảng sẽ là mảng

1 2 3 4 5 6 7 8 9 

Theo truyền thống, hình như vẫn có hai cách tiếp cận khác nhau để sáp nhập sắp xếp các mảng (lưu ý rằng trường hợp hợp nhất các danh sách liên kết là hoàn toàn khác nhau). Đầu tiên, có các thuật toán phối hợp ngoài địa điểm hoạt động bằng cách cấp phát một bộ đệm tạm thời để lưu trữ, sau đó lưu trữ kết quả của việc hợp nhất trong bộ đệm tạm thời. Thứ hai, nếu hai mảng xảy ra là một phần của cùng một mảng đầu vào, thì có in-place merge algorithms chỉ sử dụng O (1) không gian lưu trữ phụ và sắp xếp lại hai dãy liền kề vào một chuỗi được sắp xếp. Cả hai lớp thuật toán này đều chạy trong thời gian O (n), nhưng thuật toán kết hợp ngoài vị trí có xu hướng có yếu tố không đổi thấp hơn nhiều vì nó không có các yêu cầu bộ nhớ nghiêm ngặt như vậy.

Câu hỏi của tôi là liệu có một thuật toán hợp nhất đã biết có thể "nội suy" giữa hai phương pháp này hay không. Đó là, thuật toán sẽ sử dụng một nơi nào đó giữa O (1) và O (n) bộ nhớ, nhưng bộ nhớ hơn nó có sẵn cho nó, nhanh hơn nó chạy. Ví dụ, nếu chúng ta đo lường số lượng tuyệt đối của mảng đọc/ghi được thực hiện bởi các thuật toán, nó có thể có một thời gian chạy của hình thức ng (s) + f (s), trong đó s là số lượng không gian có sẵn cho nó và g (s) và f (s) là các hàm có nguồn gốc từ lượng không gian đó. Lợi thế của chức năng này là nó có thể cố gắng hợp nhất với nhau hai mảng theo cách hiệu quả nhất có thể cho các ràng buộc về bộ nhớ - bộ nhớ càng nhiều trên hệ thống, bộ nhớ càng sử dụng và (lý tưởng) hiệu năng tốt hơn .

Chính thức hơn, thuật toán sẽ hoạt động như sau. Cho như đầu vào một mảng A bao gồm hai dãy liền kề, sắp xếp, sắp xếp lại các phần tử trong mảng sao cho các phần tử hoàn toàn theo thứ tự sắp xếp. Thuật toán được phép sử dụng không gian bên ngoài, và hiệu suất của nó phải là trường hợp xấu nhất O (n) trong mọi trường hợp, nhưng nên chạy dần dần nhanh hơn với số lượng không gian phụ trợ lớn hơn để sử dụng.

Có ai quen thuộc với một thuật toán loại này (hoặc biết nơi để tìm thấy một mô tả về một?)

+1

http://stackoverflow.com/questions/3156599/merge-two-sorted-parts-of-an-array-with-constant-memory-in-on-time – necromancer

+0

@ agksmehx- Cảm ơn bạn đã liên kết. Tuy nhiên, tôi không nghĩ rằng đây là những gì tôi đang tìm kiếm.Tôi đã biết rằng bạn có thể hợp nhất vào O (1) không gian bổ sung và câu hỏi này chủ yếu là hỏi xem có cách nào để có thuật toán hợp nhất không, bạn càng cung cấp không gian càng tốt, để bạn có thể nhận được, nói, 100MB không gian thêm cho 500MB dữ liệu, bạn sẽ hợp nhất nhanh hơn nếu bạn có 10MB cho 500MB dữ liệu. – templatetypedef

+0

Đầu vào và đầu ra là gì? Tức là, bạn có đang viết vào một trong các mảng đầu vào hoặc một mảng riêng biệt không? (Tôi nghi ngờ các cựu, vì nếu nó là sau này thì đây không phải là một vấn đề.) – MSN

Trả lời

10

ít nhất là theo các tài liệu, các in-place merge function in SGI STL được thích nghi và "phức tạp thời gian chạy của nó phụ thuộc về số lượng bộ nhớ có sẵn ". Mã nguồn có sẵn tất nhiên bạn có thể ít nhất là kiểm tra này.

+0

Trong khi điều này chắc chắn hoạt động, hãy lưu ý rằng hàm này giảm xuống O (n log n) trong trường hợp xấu nhất, trong khi tồn tại các thuật toán kết hợp O-n tại chỗ tồi tệ nhất. Tôi hy vọng rằng có cái gì đó tốt hơn thế này, mặc dù O (n log n) vẫn rất tốt. – templatetypedef

2

EDIT: STL có inplace_merge, sẽ thích ứng với kích thước của bộ đệm tạm thời có sẵn. Nếu bộ đệm tạm thời ít nhất là lớn nhất là một trong các mảng con, đó là O (N). Nếu không, nó sẽ tách hợp nhất thành hai hợp nhất phụ và đệ quy. Việc chia sẽ mất O (log N) để tìm phần bên phải của mảng phụ khác để xoay trong (tìm kiếm nhị phân).

Vì vậy, nó chuyển từ O (N) sang O (N log N) tùy thuộc vào lượng bộ nhớ bạn có sẵn.

+0

Trong khi điều này chắc chắn sẽ hoạt động, nó có hành vi bệnh lý khi tất cả các mục trong 'lhs' lớn hơn mục nhỏ nhất trong' rhs'. Ví dụ, một mảng như '[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]'. Trong các trường hợp như vậy, thuật toán của bạn sẽ trở thành "sao chép' T' các mục từ 'rhs' thành' temp', di chuyển 'lhs' xuống theo vị trí' T', sao chép 'T' mục từ' temp' sang không gian mới được tạo.' Bạn kết thúc up làm '(sizeof (lhs) * sizeof (rhs))/T' di chuyển trong mảng, cộng với' 2 * (sizeof (rhs)/T) 'di chuyển từ mảng sang temp và ngược lại. Thuật toán là O (n^2), như bạn có thể thấy nếu 'T == 1'. –

+0

@JimMischel, không, nó không di chuyển' lhs', nó sao chép từ phía trước của 'lhs' vào không gian còn lại bởi' rhs'. sao chép từng phần tử từ 'lhs' nhiều nhất hai lần, chúng ta không di chuyển mảng, chỉ cần quấn liên tục vào đầu liên tục Nếu chúng ta chuyển' lhs', nó sẽ là N^2. Đó là lý do tại sao chúng ta sao chép dữ liệu – MSN

+0

Tại sao bạn loại bỏ thuật toán khác của bạn? Nó quá phức tạp và thuật toán thực tế hóa ra là đơn giản? –

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