web-dev-qa-db-fra.com

vérifier si un arbre est un arbre de recherche binaire

J'ai écrit le code suivant pour vérifier si un arbre est un arbre de recherche binaire. Aidez-moi à vérifier le code:

D'accord! Le code est édité maintenant. Cette solution simple a été suggérée par quelqu'un dans les articles ci-dessous:

IsValidBST(root,-infinity,infinity);

bool IsValidBST(BinaryNode node, int MIN, int MAX) 
{
     if(node == null)
         return true;
     if(node.element > MIN 
         && node.element < MAX
         && IsValidBST(node.left,MIN,node.element)
         && IsValidBST(node.right,node.element,MAX))
         return true;
     else 
         return false;
}
28
TimeToCodeTheRoad

Une méthode ne doit faire qu'une seule chose à la fois. De plus, la façon dont vous faites les choses est généralement bizarre. Je vais vous en donner pseudocode presque Java. Désolé pour cela, mais je n'ai pas touché Java depuis un certain temps. J'espère que cela aide. Regardez les commentaires que j'ai également fait sur la question et j'espère que vous triez!

Appelez votre isBST comme ça:

public boolean isBst(BNode node)
{
    return isBinarySearchTree(node , Integer.MIN_VALUE , Integer.MIN_VALUE);
}

En interne:

public boolean isBinarySearchTree(BNode node , int min , int max)
{
    if(node.data < min || node.data > max)
        return false;
    //Check this node!
    //This algorithm doesn't recurse with null Arguments.
    //When a null is found the method returns true;
    //Look and you will find out.
    /*
     * Checking for Left SubTree
     */
    boolean leftIsBst = false;
    //If the Left Node Exists
    if(node.left != null)
    {
        //and the Left Data are Smaller than the Node Data
        if(node.left.data < node.data)
        {
            //Check if the subtree is Valid as well
            leftIsBst = isBinarySearchTree(node.left , min , node.data);
        }else
        {
            //Else if the Left data are Bigger return false;
            leftIsBst = false;
        }
    }else //if the Left Node Doesn't Exist return true;
    {
        leftIsBst = true;
    }

    /*
     * Checking for Right SubTree - Similar Logic
     */
    boolean rightIsBst = false;
    //If the Right Node Exists
    if(node.right != null)
    {
        //and the Right Data are Bigger (or Equal) than the Node Data
        if(node.right.data >= node.data)
        {
            //Check if the subtree is Valid as well
            rightIsBst = isBinarySearchTree(node.right , node.data+1 , max);
        }else
        {
            //Else if the Right data are Smaller return false;
            rightIsBst = false;
        }
    }else //if the Right Node Doesn't Exist return true;
    {
        rightIsBst = true;
    }

    //if both are true then this means that subtrees are BST too
    return (leftIsBst && rightIsBst);
}

Maintenant: si vous voulez trouver les valeurs Min et Max de chaque sous-arbre, vous devez utiliser un conteneur (j'ai utilisé un ArrayList) et stocker un triplet de Node, Min, Max qui représente le nœud racine et les valeurs (évidemment).

par exemple.

/*
 * A Class which is used when getting subTrees Values
 */
class TreeValues
{
    BNode root; //Which node those values apply for
    int Min;
    int Max;
    TreeValues(BNode _node , _min , _max)
    {
        root = _node;
        Min = _min;
        Max = _max;
    }
}

Et un:

/*
 * Use this as your container to store Min and Max of the whole
 */
ArrayList<TreeValues> myValues = new ArrayList<TreeValues>;

Maintenant, c'est une méthode qui trouve les valeurs Min et Max d'un nœud donné:

/*
 * Method Used to get Values for one Subtree
 * Returns a TreeValues Object containing that (sub-)trees values
 */ 
public TreeValues GetSubTreeValues(BNode node)
{
    //Keep information on the data of the Subtree's Startnode
    //We gonna need it later
    BNode SubtreeRoot = node;

    //The Min value of a BST Tree exists in the leftmost child
    //and the Max in the RightMost child

    int MinValue = 0;

    //If there is not a Left Child
    if(node.left == null)
    {
        //The Min Value is this node's data
        MinValue = node.data;
    }else
    {
        //Get me the Leftmost Child
        while(node.left != null)
        {
            node = node.left;
        }
        MinValue = node.data;
    }
    //Reset the node to original value
    node = SubtreeRoot; //Edit - fix
    //Similarly for the Right Child.
    if(node.right == null)
    {
        MaxValue = node.data;
    }else
    {
        int MaxValue = 0;
        //Similarly
        while(node.right != null)
        {
            node = node.right;
        }
        MaxValue = node.data;
    }
    //Return the info.
    return new TreeValues(SubtreeRoot , MinValue , MaxValue);   
}

Mais cela renvoie des valeurs pour un Node uniquement, donc nous allons utiliser cela pour trouver pour l'arbre entier:

public void GetTreeValues(BNode node)
{
    //Add this node to the Container with Tree Data 
    myValues.add(GetSubTreeValues(node));

    //Get Left Child Values, if it exists ...
    if(node.left != null)
        GetTreeValues(node.left);
    //Similarly.
    if(node.right != null)
        GetTreeValues(node.right);
    //Nothing is returned, we put everything to the myValues container
    return; 
}

En utilisant ces méthodes, votre appel devrait ressembler à

if(isBinarySearchTree(root))
    GetTreeValues(root);
//else ... Do Something

C'est presque Java. Cela devrait fonctionner avec quelques modifications et correctifs. Trouvez un bon livre OO, cela vous aidera. Notez que cette solution pourrait être décomposée en plusieurs méthodes.

5
user418748

à droite, une autre solution simple est de faire une visite inorder

code Java ici

11
alex
boolean bst = isBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE);

public boolean isBST(Node root, int min, int max) {
    if(root == null) 
        return true;

    return (root.data > min &&
            root.data < max &&
            isBST(root.left, min, root.data) &&
            isBST(root.right, root.data, max));
    }
5
Arif Saikat

MISE À JOUR: Je viens de voir que cette solution a été suggérée auparavant. Désolé pour ce gars, peut-être que quelqu'un trouve toujours ma version utile

Voici une solution qui utilise In-Order Traversal pour vérifier la propriété BST. Avant de fournir la solution, j'utilise une définition d'un BST qui n'autorise pas les doublons. Cela signifie que chaque valeur dans le BST est unique (c'est juste pour la simplicité).

Code pour l'impression récursive inorder:

void printInorder(Node root) {
    if(root == null) {                 // base case
        return;
    }
    printInorder(root.left);           // go left
    System.out.print(root.data + " "); // process (print) data
    printInorder(root.right);          // go right
}

Après cette traversée dans l'ordre sur un BST, toutes les données doivent être imprimées dans l'ordre croissant. Par exemple, l'arbre:

   5
 3   7
1 2 6 9

aurait inorder imprimer:

1 2 3 5 6 7 9

Maintenant, au lieu d'imprimer le nœud, nous pouvons garder une trace de la valeur précédente dans la séquence en ordre et la comparer à la valeur du nœud actuel. Si la valeur du nœud actuel est inférieure à la valeur précédente, cela signifie que la séquence n'est pas dans l'ordre trié croissant et que la propriété BST est violée.

Par exemple, l'arbre:

   5
 3   7
1 8 6 9

A une violation. L'enfant droit de 3 est 8 et ce serait correct si 3 était le nœud racine. Cependant, dans un BST 8 finirait comme un enfant gauche de 9 et non en tant qu'enfant droit de 3 . Par conséquent, cet arbre n'est pas un BST. Donc, le code qui suit cette idée:

/* wrapper that keeps track of the previous value */
class PrevWrapper {
    int data = Integer.MIN_VALUE;
}

boolean isBST(Node root, PrevWrapper prev) {
    /* base case: we reached null*/
    if (root == null) {
        return true;
    }

    if(!isBST(root.left, prev)) {
        return false;
    }
    /* If previous in-order node's data is larger than
     * current node's data, BST property is violated */
    if (prev.data > root.data) {
        return false;
    }

    /* set the previous in-order data to the current node's data*/
    prev.data = root.data;

    return isBST(root.right, prev);
}

boolean isBST(Node root) {
    return isBST(root, new PrevWrapper());
}

La traversée dans l'ordre de l'arborescence exemple échouerait la vérification du nœud 5 depuis l'ordre précédent de 5 est 8 , ce qui est plus grand de sorte que la propriété BST est violée.

4
nem035
    boolean isBST(TreeNode root, int max, int min) {
        if (root == null) {
            return true;
        } else if (root.val >= max || root.val <= min) {
            return false;
        } else {
            return isBST(root.left, root.val, min) && isBST(root.right, max, root.val);
        }

    }

une manière alternative de résoudre ce problème .. similaire avec votre code

2
Zzz...

Un arbre de recherche binaire a les propriétés suivantes où la clé du nœud gauche doit être <= la clé du nœud racine et la clé du nœud droit doit être supérieure à la racine.

Donc, le problème que nous avons est que si les clés de l'arborescence ne sont pas uniques et qu'une traversée dans l'ordre a été effectuée, nous pourrions obtenir une situation de deux traversées dans l'ordre produisant la même séquence, où 1 serait un bst valide et l'autre non, cela se produirait si nous avions un arbre où le nœud gauche = racine (bst valide) et le nœud droit = ​​racine (non valide pas un bst).

Pour contourner ce problème, nous devons maintenir une plage min/max valide entre laquelle la clé "visitée" doit se situer, et nous transmettons cette plage au fur et à mesure que nous récursions vers d'autres nœuds.

#include <limits>

int min = numeric_limits<int>::min();
int max = numeric_limits<int>::max();

The calling function will pass the above min and max values initially to isBst(...)

bool isBst(node* root, int min, int max)
{
    //base case
    if(root == NULL)
        return true;

    if(root->val <= max && root->val >= min)
    {
        bool b1 = isBst(root->left, min, root->val);
        bool b2 = isBst(root->right, root->val, max);
        if(!b1 || !b2)
            return false;
        return true;
    }
    return false;
}
1
gilla07

Cela n'a pas vraiment de sens de renvoyer INTEGER.MIN, INTEGER.MAX comme valeurs pour une arborescence vide. Utilisez peut-être un entier et retournez null à la place.

0
monkjack
public void inorder()
     {
         min=min(root);
         //System.out.println(min);
         inorder(root);

     }

     private int min(BSTNode r)
         {

             while (r.left != null)
             {
                r=r.left;
             }
          return r.data;


     }


     private void inorder(BSTNode r)
     {

         if (r != null)
         {
             inorder(r.getLeft());
             System.out.println(r.getData());
             if(min<=r.getData())
             {
                 System.out.println(min+"<="+r.getData());
                 min=r.getData();
             }
             else
             System.out.println("nananan");
             //System.out.print(r.getData() +" ");
             inorder(r.getRight());
             return;
         }
     }
0
kireet

Nous parcourons l'arbre en profondeur d'abord, testant la validité de chaque nœud au fur et à mesure. Un nœud donné est valide s'il est supérieur à tous les nœuds ancestraux, il se trouve dans le sous-arbre droit et inférieur à tous les nœuds ancestraux, il se trouve dans le sous-arbre gauche de. Au lieu de garder une trace de chaque ancêtre pour vérifier ces inégalités, nous vérifions simplement le plus grand nombre, il doit être supérieur à (sa limite inférieure) et le plus petit nombre, il doit être inférieur à (sa limite supérieure).

 import Java.util.Stack;

final int MIN_INT = Integer.MIN_VALUE;
final int MAX_INT = Integer.MAX_VALUE;

public class NodeBounds {

BinaryTreeNode node;
int lowerBound;
int upperBound;

public NodeBounds(BinaryTreeNode node, int lowerBound, int upperBound) {
    this.node = node;
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
}
}

public boolean bstChecker(BinaryTreeNode root) {

// start at the root, with an arbitrarily low lower bound
// and an arbitrarily high upper bound
Stack<NodeBounds> stack = new Stack<NodeBounds>();
stack.Push(new NodeBounds(root, MIN_INT, MAX_INT));

// depth-first traversal
while (!stack.empty()) {
    NodeBounds nb = stack.pop();
    BinaryTreeNode node = nb.node;
    int lowerBound = nb.lowerBound;
    int upperBound = nb.upperBound;

    // if this node is invalid, we return false right away
    if ((node.value < lowerBound) || (node.value > upperBound)) {
        return false;
    }

    if (node.left != null) {
        // this node must be less than the current node
        stack.Push(new NodeBounds(node.left, lowerBound, node.value));
    }
    if (node.right != null) {
        // this node must be greater than the current node
        stack.Push(new NodeBounds(node.right, node.value, upperBound));
    }
}

// if none of the nodes were invalid, return true
// (at this point we have checked all nodes)
return true;
}
0
CHANTAL COX