Be careful with recursion---take recursive binary search as an example

Source: Internet
Author: User

Yesterday when the interview was asked a lot of questions, and then do, some parts unexpectedly connected: Binary search, recursive, local variables static variables (static local variables), there may be more, I slowly summed up.

OK, get in the chase.

First,

First, write a binary lookup function. Because before just know this algorithm, the actual writing has not written, think about, if not recursive, a moment no idea, then use recursion it

//This is v0.1 and there could be errors.#include <stdio.h>intBinary_search (intA[],intLeftintRightintkey) {    if(Left <Right ) {        intMid = (left+right)/2; if(Key >A[mid]) Binary_search (A, Mid, right, key); Else if(Key <A[mid]) Binary_search (A, left, Mid, key); Else            returnmid; }    return-1;//Not 0, or there is conflict with the [index]-0 of array}intMain () {inta[6]={1,2,3,4,5,6}; intKey =5; printf ("%d\n", Binary_search (A,0,5, key)); return 0;}

Try it with Xcode. Hey, how did it go wrong.

Read a few times did not come up with a why, then step by step write it.

1).

First change the key, when the key=3, can output the correct results, other cases will output-1

2).

Then, taking key=5 as an example, here is a rough process

Figure A

As can be seen from figure one, the last thing is to find the key subscript, if we add a sentence as follows printf ("succeed!");

if (Key > a[mid])     return Binary_search (A, Mid, right, key); Else if (Key < A[mid])     return Binary_search (A, left, Mid, key); Else {    printf ("succeed!");     return mid;}

Finally, I can print out "succeed!" on the console. Of

3).

Compared to the recursive code found elsewhere, the problem is mainly found in

if (Key > a[mid])    Binary_search  (A, Mid, right, key); Else if (Key < A[mid])    return Binary_search (A, left, Mid, key); Else    return mid;

Missing red Word part return

Missing red Word part return

Missing red Word part return

What results does this lead to? We know that the return will end the function, but this is not the end of the "whole function", just end this call, just like nested loops, inside the break only breaks inside a layer of loops, will not break the two-layer loop at a time. Thus, if only the last else inside has return, then, after finding the subscript in figure one, just return returns the end of the third call, return to the second block after the end of this, or will continue to go through the second block if (left<right) {...} The rest of the content, then return (second block)-1; This is the end of the second block, back to the first block, and then the same, continue to walk the first block if (left<right) {...} The rest of the content, then return (the first piece)-1; Ends the "entire function" call, so the final reutrn is not to find the subscript, rather than to find the subscript after a layer of exit and do not perform the rest of the last content to return the expected subscript. Well, that's the result of the not-so-solid foundation. Slowly fill it up, a loophole every day is a point of progress. The problem was not found in the previous practice, because the address was directly passed in, and then the corresponding address element has been modified, just to be able (and do not change the sorted array) to stop recursion. It's still a little dangerous, though.

TODO: Then modify the functions that use recursion and return them.

Second,

1).

OK again back to the theme, figured out the above, I suddenly thought, can set a flag, the last value to flag it, or so, directly from the beginning to initialize the flag to 1, and then if found that the flag changed to subscript value, if not found that still the original-1, Finally return flag, so do not if (Left<right) {...} There's no harm in the return (in fact, it's wrong). But let's see what happens after that.

//This is v0.2 and there could be errors.#include <stdio.h>intBinary_search (intA[],intLeftintRightintkey) {    intKey_index =-1; if(Left <Right ) {        intMid = (left+right)/2; if(Key >A[mid]) Binary_search (A, Mid, right, key); Else if(Key <A[mid]) Binary_search (A, left, Mid, key); ElseKey_index=mid; }    returnKey_index;}intMain () {inta[6]={1,2,3,4,5,6}; intKey =6; printf ("%d\n", Binary_search (A,0,5, key)); return 0;}

Let's run it, eh. Why did you die? Repeat this, but if you change the key to 4, you can run it, though the result is: Yes-1

How can this, the original problem did not solve, and encountered other problems. Ah no hurry, there is a problem on a solution Bai, there will always be a way to learn in error, and then the process to record down the memo.

2).

Compare other people's programs, and follow the Tuyi method to do it again, you can find the cause of the death: missing the following scarlet letter part

if (Key > a[mid])    Binary_search (A, mid+1, right, key);

This mid+1 not only makes the next search interval smaller ((mid+1) The->right interval is smaller than mid->right) and is necessary, incidentally, by pointing to another vulnerability (The Scarlet Letter part)

if (left<=right)

These two places can cause problems because the right boundary cannot be taken .

int mid = (left+right)/2

The subscript for the middle value is divided evenly, and an example is used to illustrate the problem.

(3+5)/2=4//ok
(3+3)/2=4//ok
(3+4)/2=3//divisible to No right boundary

And in the If-else, we have put (key = = A[mid]) of the situation is written out, if it is equal, then go to the last else, if not equal, it is not necessary in the next search time to write this boundary in, greater than when the left border is directly mid+1. If you still use the method of figure one, and key=6, then the program will always be Binary_search (A, 4, 5, 6) does not go out

Figure II

Ps: Actually should think of, because before in the merger sort of time also considered this question,

An array that starts with a[0]. A[n-1] left=0, right=n-1

From the middle into two segments, Mid = (left+right)/2, then

The interval on the left is A[left]. A[mid]

The right-hand interval subscript is a[mid+1], A[right]

3).

So we're going to fix the bug as follows (the Scarlet Letter section)

//This is v0.3 and there could be errors.#include <stdio.h>intBinary_search (intA[],intLeftintRightintkey) {    intKey_index =-1; if(Left <=Right ) {        intMid = (left+right)/2; if(Key >A[mid]) Binary_search (A, Mid+1, right, key); Else if(Key <A[mid]) Binary_search (A, left, Mid, key); ElseKey_index=mid; }    returnKey_index;}intMain () {inta[6]={1,2,3,4,5,6}; intKey =6; printf ("%d\n", Binary_search (A,0,5, key)); return 0;}

Three

Well, everything seems to be done, let's try it again. Well, as mentioned earlier, or error, output or 1

warum?!

Ok nonsense less say, here the logic error to involve the scope of the variable

1).

Here says:

Local variables are also only local scope, it is an automatic object (auto), it does not persist during the program run, but only during the execution of the function, the function of the execution of a call after the end of the variable is revoked, the memory occupied by the recovery.

Or take figure one as an example, because of the location defined by Key_index, each piece of the three block area will create a key_index, which we remember as KEY_INDEX1, Key_index2, Key_index3. Since only the last piece, which satisfies (key = = A[mid]), enters the statement with the Key_index assignment (other places do not meet the conditions), that is, Key_index3=mid, well, when return key_index3 back to the second block , Key_index3 was wiped out, and because Key_index2 did not come to receive key_index3, so key_index2 or 1, let alone key_index1, so in the outermost layer return key_index; , the key_index1 is actually returned without change, so it's still 1.

2).

The corresponding solution

I. Add a statichere, the result is OK ~

intBinary_search (intA[],intLeftintRightintkey) {    Static intkey_index=-1; if(left<=Right ) {        intMid= (left+right)/2; if(key>A[mid]) Binary_search (A, Mid+1, right, key); Else if(key<A[mid]) Binary_search (A, left, Mid, key); Else{Key_index=mid; }    }        returnKey_index;}

Because here says:

A static local variable has a local scope, it is initialized only once, and since the first initialization until the end of the program runs, it differs from the global variable in that the global variable is visible to all functions, while static local variables are always visible to the body of the function that defines itself.

In other words, adding a static is equivalent to associating Key_index1, 2, 3 in a function, which actually turns into the same variable, so the last key

II. or (The Scarlet Letter part)

intBinary_search (intA[],intLeftintRightintkey) {    intKey_index =-1; if(Left <=Right ) {        intMid = (left+right)/2; if(Key >A[mid]) Key_index =Binary_search (A, mid+1, right, key); Else if(Key <A[mid]) Key_index =Binary_search (A, left, Mid, key); Else{ Key_index =  mid; }    }        return key_index;}

III. Or a flag from the outside, it should be. But those are the best things to do with research, and it's better to use a generic one, not to reduce the legibility of the program, nor to add complexity.

So now you can give a bug-fixed version of the program, or the method of return by layer (and can get the right edge)

//binary Search//v0.4, Bugs fixed#include <stdio.h>intBinary_search (intA[],intLeftintRightintkey) {    if(left<=Right ) {        intMid= (left+right)/2; if(key>A[mid])returnBinary_search (A, mid+1, right, key); Else if(key<A[mid])returnBinary_search (A, left, Mid, key); Else            returnmid; }        return-1; //not 0, or there may is conflict with the [index]-0 of the array}intMain () {inta[6]={1,2,3,4,5,6}; intkey=6; printf ("%d", Binary_search (A,0,5, key));}

For the time being here first, at night in retrospect again, and then

$ GIT push origin master

To Learngit, so that all the way to be able to have several commits happy:)

Be careful with recursion---take recursive binary search as an example

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.