2011-06-26 12 views
7

Quicksort này được coi là sắp xếp "v [left] ... v [right] thành thứ tự tăng dần"; sao chép (không có bình luận) từ Ngôn ngữ lập trình C của K & R (Second Edition):Lỗi trong ví dụ quicksort (sách K & R C)?

void qsort(int v[], int left, int right) 
{ 
    int i, last; 
    void swap(int v[], int i, int j); 

    if (left >= right) 
     return; 
    swap(v, left, (left + right)/2); 
    last = left; 
    for (i = left+1; i <= right; i++) 
     if (v[i] < v[left]) 
      swap(v, ++last, i); 
    swap(v, left, last); 
    qsort(v, left, last-1); 
    qsort(v, last+1, right); 
} 

Tôi nghĩ rằng có một lỗi ở

(left + right)/2 

Giả sử trái = INT_MAX - 1 và ngay = INT_MAX. Điều này sẽ không dẫn đến hành vi không xác định do tràn số nguyên không?

+3

Nó có lẽ được lập trình với giả định rằng một mảng sẽ không lớn như vậy khi chạy. :) – sarnold

+0

Đó là một giả định rất tốt vì bạn sẽ không có không gian trong bộ nhớ cho chương trình quicksort của bạn –

+1

Xem thêm: http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it -nearly.html –

Trả lời

7

Có, bạn nói đúng. Bạn có thể sử dụng left - (left - right)/2 để tránh bị tràn.

+0

những gì tràn? –

+0

Giải pháp tuyệt vời !!! – functionptr

+4

@Jerry: ITYM: 'left + (phải-trái)/2' –

2

Bạn không tưởng tượng ra một mảng có số lượng thành phần INT_MAX, phải không?

+2

Đó chỉ là dưới 8 gigabyte không gian địa chỉ, giả sử số nguyên 32 bit. Nhiều hơn doable trên phần cứng hiện đại. :) – sarnold

+2

Chúng tôi có lẽ sẽ phải tha thứ cho K & R vì không xem xét bộ nhớ phát triển từ kB đến GB. Và "640k là đủ cho mọi người"? –

+0

@Bó có nền tảng với 16-bit 'int', bạn biết, và tôi khá chắc chắn một số người trong số họ có hơn 64Kb bộ nhớ. 'int'! =' intptr_t'. –

1

Có, bạn nói đúng, mặc dù nó có thể chỉ được viết theo cách đó để đơn giản - đó là một ví dụ sau khi tất cả, không phải mã sản xuất.

1

K & R luôn hơi cẩu thả với việc sử dụng các đối số chưa được ký và đã ký. Tác dụng phụ của việc làm việc với PDP chỉ có 16 kilobyte bộ nhớ mà tôi cho là. Đó là cố định một thời gian trước đây. Định nghĩa hiện tại của qsort là

void qsort(
    void *base, 
    size_t num, 
    size_t width, 
    int (__cdecl *compare)(const void *, const void *) 
); 

Lưu ý việc sử dụng size_t thay vì int. Và tất nhiên là void * base vì bạn không biết loại bạn đang phân loại là gì.

+1

Wart '__cdecl' không phải là một phần của định nghĩa chuẩn. – caf

+0

Tôi chắc chắn đó là sự thật, họ có thể chỉ có * một * quy ước gọi trở lại sau đó. Và ít hơn nhiều từ khóa bắt đầu với * hai * dấu gạch dưới. Hãy để nó cho các nhà cung cấp để làm cho nó phức tạp. Nhất thiết như vậy, tiêu chuẩn kinda sux. –