2010-06-03 10 views
13

Tôi đang cố gắng hiểu các yêu cầu về không gian cho một Mergesort, O (n).
Tôi thấy rằng các yêu cầu về thời gian về cơ bản là, mức độ (logn) * hợp nhất (n) sao cho tạo (n log n).
Bây giờ, chúng tôi vẫn phân bổ n cho mỗi cấp độ, trong 2 mảng khác nhau, trái và phải.
Tôi hiểu rằng chìa khóa ở đây là khi các hàm đệ quy trả về không gian bị deallocated, nhưng tôi không thấy nó quá rõ ràng.
Bên cạnh đó, tất cả thông tin tôi tìm thấy, chỉ cần nêu rõ không gian được yêu cầu là O (n) nhưng không giải thích được.
Bất kỳ gợi ý nào?Các yêu cầu về không gian của một sắp xếp hợp nhất

function merge_sort(m) 
    if length(m) ≤ 1 
     return m 
    var list left, right, result 
    var integer middle = length(m)/2 
    for each x in m up to middle 
     add x to left 
    for each x in m after middle 
     add x to right 
    left = merge_sort(left) 
    right = merge_sort(right) 
    result = merge(left, right) 
    return result 

EDIT Ok, nhờ @Uri, đây là lừa
Những gì tôi không nhìn thấy ở đầu là thời gian mà chỉ cho biết thêm, trong khi bộ nhớ cộng và trừ, vì vậy số tiền tối đa thời gian là lúc kết thúc thực hiện, nhưng số lượng tối đa của bộ nhớ là ở dưới cùng của ngăn xếp đệ quy.

Vì vậy, nếu chúng ta tiếp tục thêm n + n/2 + n/4 + n/8 .... không quan trọng số lần chúng ta thêm vào, nó sẽ không bao giờ lớn hơn 2n và khi chúng ta đạt đến đáy stack đệ quy và bắt đầu đi lên, chúng tôi không giữ bộ nhớ được sử dụng cho các chi nhánh trước đó, do đó, tại tối đa, 2n sẽ là số lượng bộ nhớ được sử dụng, O (n).

Trả lời

14

Có các phiên bản sắp xếp hợp nhất có thể hoạt động tại chỗ.

Tuy nhiên, trong hầu hết các triển khai, không gian là tuyến tính theo kích thước của mảng. Điều đó có nghĩa là n cho cấp độ đầu tiên, n/2 cho lần thứ hai, n/4 cho lần thứ ba, v.v. Vào thời điểm bạn đang ở dưới cùng của đệ quy của bạn, chuỗi này thêm lên đến khoảng 2n, đó là tuyến tính.

+0

@Arkaitz: "Triển khai nhiều nhất" bao gồm triển khai bạn đã đăng. – Brian

+0

Tôi đã đăng những gì tôi hiểu bây giờ, sửa tôi nếu sai xin vui lòng. –

+0

Bạn hiểu chính xác. Vấn đề là với mã giả, Nó dễ dàng hơn để hình dung điều khiển (và do đó thời gian phức tạp) hơn là nội dung của ngăn xếp cuộc gọi. – Uri

0

Đây là giải thích của tôi về sự phức tạp về không gian cho mã của bạn. Về cơ bản, khi thuật toán đạt được kết quả, chúng ta đang làm việc như thế nào trên bộ nhớ.

1) Mọi cuộc gọi đệ quy bạn thực hiện có kích thước không đổi của khung ngăn xếp được phân bổ cũng như bất kỳ biến nào không phải là hàm của "n". Hãy gọi điều này constanct "c". Vì, bạn đang đi lg (n) cấp sâu kết quả là c * lg (n) là O (lg (n)).

2) Bây giờ, khi tính toán kết quả, chúng tôi phân bổ không gian cho các phần tử n/(2^k), trong đó k là cấp độ của bạn.

left = merge_sort(left) 
right = merge_sort(right) 

Đối với folks người có thể tự hỏi làm sao chúng ta đã đưa ra n/(2^k), thông báo rằng đầu tiên chúng tôi đi về cấp phát bộ nhớ khi giải quyết nửa đầu của mảng tức là trái = merge_sort (bên trái). Một lần, cây đệ quy này đã kết thúc, chúng ta sẽ kết thúc deallocating tất cả bộ nhớ và quay trở lại điểm bắt đầu trước khi giải quyết cho phía bên phải. Do đó, n/(2^k) của nó. Đây sẽ là O (n).

3) Cuối cùng, sáp nhập thủ tục có thể phân bổ thêm không gian quá (nếu sử dụng danh sách liên kết không gian này có thể không cần thiết) là O (n)

cuối cùng câu trả lời = O (lg (n)) + O (n) + O (n) là O (n).