1

I was trying to write a code to determine if a tree is a BST.
And I searched the solution from website for reference.
One of the solutions is as follows:
I really don't get how static pointer serves in this function.
Can anyone explain to me? Thank you so much!

Here is the code fragment.

int isBSTtree(treeNode *T)
{
    static treeNode *prev=NULL;
    if(T)
    {
        if(!isBSTtree(T->left))
        {
            return 0;
        }
        if(prev!=NULL && T->value<=prev->value)
        {
            return 0;
        }
        prev=T;
        return isBST(T->right);
    }
    return 1;
}
Liu
  • 413
  • 4
  • 11
  • `static` variables have a single instance in the memory unlike the automatic variables which instantiate with each call to the function. That's pretty much of it. Think of it defined in global scope which is almost the same (except the "visibility"). – Eugene Sh. Apr 12 '19 at 15:58
  • The static variable allows you to save the value between calls to the function. – BugSquasher Apr 12 '19 at 15:59
  • 3
    Anyway, as a fond of purity in function I consider using static/global variables in recursive functions a "cheating". – Eugene Sh. Apr 12 '19 at 16:02
  • 2
    It's not only "cheating". Using a `static` variable means that you can perform the check reliably only once. After that, `prev` will be the highest (monotonic) value and the check will fail. – M Oehm Apr 12 '19 at 16:38
  • @JohnBollinger That's almost certainly just a typo. Both the left and right subtrees need to be tested for BSTness, and the logic to do so would be the same in each case. – Ray Apr 12 '19 at 17:42
  • After thinking about it a bit more, @Ray, I think you're right. I have deleted my previous comment. – John Bollinger Apr 12 '19 at 18:03

2 Answers2

1

Static variables preserve their values between function calls. If they are initialized as part of the declaration, as in static treeNode *prev=NULL;, the initialization happens exactly once.

So for instance, if you have f:

void f(int n) {
    static int x = 4;

    if (!n) {
        printf(" : ");
        return;
    }

    x += 2;
    printf("%d ", x);
    f(n - 1);
    printf("(%d) ", x); 
}

Then f(3) will print 6 8 10 (10) (10) (10). The static variable is used both to pass a value to the recursive call and to get a value back. In the case of the BST check, that's being used to find the value of the rightmost element of the left subtree.

But there are a couple issues with doing it that way.

f(3); putchar('\n'); f(3); prints

6 8 10 (10) (10) (10)
12 14 16 (16) (16) (16)

because we forgot to reset the static variable between non-recursive calls. And if we call f(3) from two different threads at the same time, the same static variable is used in both calls, and there's no telling what order the numbers will come out in.

The logic behind isBSTtree is to do a left to right traversal, keeping track of the greatest element seen thus far, and indicates failure if it the greatest element seen to the left of a node is greater than the node's value. So a better way to do it would be:

int isBSTaux(treeNode *T, treeNode **prev) {
    if(!T) return 1;

    if (!isBSTaux(T->left, prev)) return 0;
    if (*prev && (*prev)->value > T->value) return 0;
    *prev = T;
    return isBSTaux(T->right, prev);
}

int isBSTtree(treeNode *root) {
   treeNode *prev = NULL;
   return isBSTaux(root, &prev);
}

Each call to isBSTtree gets its own copy of prev, which is reinitialized each time through, and is not shared between different calls.

(Which is not to say that static local variables don't have their uses; they just aren't the right choice in this particular case.)

Ray
  • 1,706
  • 22
  • 30
0

static will retain the value of variables between function calls again and again since it is calling itself again and again(recursion) you need to retain the value of prev variable

Mohit Jain
  • 270
  • 2
  • 6