Tôi đang gặp khó khăn trong việc tìm hiểu cảm ứng, kết hợp với một số bất biến, có thể được sử dụng để chứng minh tính chính xác của thuật toán. Cụ thể, làm thế nào là bất biến được tìm thấy, và khi nào là giả thuyết quy nạp được sử dụng - đặc biệt cho tìm kiếm nhị phân? Tôi đã không thể tìm thấy một phản ứng trực quan, vì vậy tôi đã hy vọng một ai đó có thể làm sáng tỏ một số chủ đề ở đây.Làm thế nào chúng ta có thể chứng minh bằng cảm ứng rằng tìm kiếm nhị phân là chính xác?
Trả lời
Giả sử rằng tìm kiếm nhị phân được xác định như thế này:
def binary_search(a,b,e,x):
n = e-b
if n==0: return None
m = b + int(n/2)
if x<a[m]: return binary_search(a,b,m,x)
if x>a[m]: return binary_search(a,m+1,e,x)
return m
Nơi
- a là mảng các giá trị - giả sắp xếp
- [b, e) là phạm vi từ b đến e, bao gồm b nhưng không bao gồm điện tử, mà chúng tôi đang tìm kiếm thông qua.
- x là giá trị chúng tôi đang tìm kiếm
Mục tiêu của chức năng là để trở về tôi đâu a [i] == x nếu có như vậy giá trị của tôi, nếu không trở về None.
binary_search làm việc cho một loạt các kích cỡ bằng không:
- Chứng minh: Nếu phạm vi không chứa yếu tố, sau đó n == 0 và hàm trả về Không, đó là chính xác.
Giả sử binary_search hoạt động cho một loạt các phần tử có kích thước từ 0 đến n, khi đó tìm kiếm nhị phân hoạt động cho một loạt các thành phần có kích thước n + 1.
Proof:
Vì mảng được sắp xếp, nếu x < a [m], sau đó x < a [k] cho tất cả k> m. Điều này có nghĩa là chúng ta chỉ cần tìm kiếm phạm vi [b, m]. Phạm vi [b, m) nhất thiết phải nhỏ hơn phạm vi [b, e) và chúng tôi giả định rằng tìm kiếm nhị phân hoạt động cho tất cả các phạm vi có kích thước nhỏ hơn n + 1, vì vậy nó sẽ hoạt động cho [b, m).
Nếu x> a [m], thì logic tương tự sẽ áp dụng.
Nếu x == a [m], thì hàm sẽ trả về m, đúng.
/** Return an index of x in a.
* Requires: a is sorted in ascending order, and x is found in the array a
* somewhere between indices left and right.
*/
int binsrch(int x, int[] a, int left, int right) {
while (true) {
int m = (left+right)/2;
if (x == a[m]) return m;
if (x < a[m])
r = m−1;
else
l = m+1;
}
}
Quan sát chính là binsrch hoạt động theo kiểu phân chia và chinh phục, tự gọi chỉ trên các đối số "nhỏ hơn" theo một cách nào đó.
Cho P (n) là xác nhận rằng binsrch hoạt động chính xác cho các đầu vào trong đó phải − left = n. Nếu chúng ta có thể chứng minh rằng P (n) là đúng cho tất cả n, thì chúng ta biết rằng binsrch hoạt động trên tất cả các đối số có thể.
Trường hợp cơ bản. Trong trường hợp n = 0, chúng ta biết left = right = m. Vì chúng ta giả định rằng hàm sẽ chỉ được gọi khi x được tìm thấy giữa trái và phải, nó phải là trường hợp x = a [m], và do đó hàm sẽ trả về m, một chỉ mục của x trong mảng a.
Bước quy nạp. Chúng tôi giả định rằng binsrch hoạt động miễn là trái − phải ≤ k. Mục tiêu của chúng tôi là chứng minh rằng nó hoạt động trên đầu vào bên trái − bên phải = k + 1. Có ba trường hợp, trong đó x = a [m], trong đó x < a [m] và trong đó x> a [m].
Case x = a[m]. Clearly the function works correctly.
Case x < a[m]. We know because the array is sorted that x must be found between a[left] and a[m-1]. The n for the recursive call is n = m − 1 − left = ⌊(left+right)/2⌋ − 1 − left. (Note that ⌊x⌋ is the floor of x, which rounds it down toward negative infinity.) If left+right is odd, then n = (left + right − 1)/2 − 1 − left = (right − left)/2 − 1, which is definitely smaller than right−left. If left+right is even then n = (left + right)/2 − 1 − left = (right−left)/2, which is also smaller than k + 1 = right−left because right−left = k + 1 > 0. So the recursive call must be to a range of a that is between 0 and k cells, and must be correct by our induction hypothesis.
Case x > a[m]. This is more or less symmetrical to the previous case. We need to show that r − (m + 1) ≤ right − left. We have r − (m + 1) − l = right − ⌊(left + right)/2⌋ − 1. If right+left is even, this is (right−left)/2 − 1, which is less than right−left. If right+left is odd, this is right− (left + right − 1)/2 − 1 = (right−left)/2 − 1/2, which is also less than right−left. Therefore, the recursive call is to a smaller range of the array and can be assumed to work correctly by the induction hypothesis.
Vì trong mọi trường hợp, quy trình bước quy nạp đều có thể kết luận rằng binsrch (và biến thể lặp lại của nó) là chính xác!
Lưu ý rằng nếu chúng tôi đã nhầm lẫn mã hóa trường hợp x> a [m] và chuyển m sang trái thay vì m + 1 (dễ thực hiện!), Bằng chứng chúng tôi vừa tạo sẽ không thành công trong trường hợp đó . Và trên thực tế, thuật toán có thể đi vào vòng lặp vô hạn khi phải = trái + 1. Điều này cho thấy giá trị của lý luận quy nạp cẩn thận.
tham khảo: http://www.cs.cornell.edu/Courses/cs211/2006sp/Lectures/L06-Induction/binary_search.html
Bạn nên chứng minh rằng sau mỗi bước tìm kiếm nhị phân arr[first] <= element <= arr[last]
Từ này và chấm dứt, bạn có thể kết luận rằng tìm kiếm một lần nhị phân chấm dứt arr[first] == element == arr[last]
Giả sử mảng được sắp xếp là a[0...n]
. Tìm kiếm nhị phân hoạt động bằng cách phân chia đệ quy mảng này thành ba phần, phần tử giữa m
, phần bên trái trong đó tất cả các phần tử là <= m
(vì mảng được sắp xếp theo giả định) và phần bên phải tất cả các phần tử là >=m
(một lần nữa, bởi vì mảng được sắp xếp theo giả định).
Làm thế nào để xây dựng sự bất biến?
Trước hết hãy nghĩ về cách hoạt động của tìm kiếm nhị phân. Nếu khóa (mục đang được tìm kiếm) là k
thì tôi so sánh nó với phần tử ở giữa m
.
Nếu
k = m
, tôi đã tìm thấy mục của tôi (không có gì hơn để làm)Nếu
k < m
sau đó tôi biết chắc chắn rằng nếuk
xuất hiện tronga
, nó không thể xuất hiện trong phần bên phải của mảng vì tất cả các phần tử trên phần đó của mảng là>= m > k
. Vì vậy, nó phải xuất hiện (nếu có) trong phần bên trái của mảng.Nếu
k > m
thì tôi biết chắc chắn ......
Vì vậy, những gì chúng ta có thể bảo lãnh tại mỗi bước của một tính toán đệ quy như vậy? Ở mỗi bước, chúng tôi có thể xác định hai chỉ số i, j
và xác nhận rằng "nếu k
là một phần tử của a[0...n]
thì phải xuất hiện ở giữa i, j
".Đây là bất biến bởi vì nó giữ cho tất cả các bước đệ quy và mỗi bước bạn ép dải này i, j
cho đến khi bạn tìm thấy mục của bạn hoặc phạm vi này trở nên trống (phạm vi không trống khi i < j
).
Cảm ứng hoạt động như thế nào?
Đối với trường hợp cơ sở bạn lấy
i = 0, j = n
. Các bất biến giữ tầm thường.Đối với bước quy nạp, giả sử giữ bất biến đối với một số bước đệ quy
p
trong đói = i_p & j = j_p
. Và sau đó bạn phải chứng minh rằng cho bước đệ quy tiếp theo,i, j
được cập nhật sao cho bất biến vẫn giữ. Đây là nơi bạn phải sử dụng các đối số trong bước 2) và 3) ở trên.Phạm vi
i, j
bị giảm nghiêm trọng, do đó việc tính toán phải kết thúc.
Tôi có bỏ lỡ điều gì không?