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

j'ai écrit le code suivant pour vérifier si un arbre Binaire est un arbre de recherche. Merci de m'aider à vérifier le code:

Ok! Le code est édité maintenant. Cette solution simple a été suggérée par quelqu'un dans les billets 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;
}
27
demandé sur Pete Kirkham 2011-01-01 22:34:01

9 réponses

Une Méthode ne doit faire qu'une chose à la fois. Et la façon dont tu fais les choses est généralement Bizarre. Je vais vous donner quelques presque - Java pseudocode. Désolé pour ça, mais je n'ai pas touché à Java depuis un moment. J'espère que cela aide. Regardez les commentaires que j'ai également faits sur la Question et j'espère que vous réglerez cela!

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 le Min et Max Valeurs de chaque sous-arbre, vous devez utiliser un récipient (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 :

/*
 * 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 le Min et Max valeurs 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 ceci renvoie des valeurs pour un seul noeud, donc nous allons utiliser ceci 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 cette méthode, 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 D'OO, il vous aidera. Notez que cette solution pourrait être décomposée en plusieurs méthodes.

5
répondu Muggen 2011-01-02 13:42:47

droite, une autre solution simple est de faire une visite ordonnée

code java ici

11
répondu alex 2012-07-30 20:35:54
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
répondu Arif Saikat 2014-07-11 01:03:33

mise à jour: je viens de voir que cette solution a déjà été suggérée. Désolé les gars, peut-être quelqu'un trouve encore ma version utile

Voici une solution qui utilise Dans L'Ordre Transversal pour vérifier la propriété DE BST. Avant de fournir la solution, j'utilise une définition D'un TSB qui ne permet pas les doublons. Cela signifie que chaque valeur dans le TSB est unique (c'est juste pour la simplicité).

Code récursif afinde imprimer:

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 cet ordre de traversée sur un TSB, toutes les données doivent être imprimées dans l'ordre croissant. Par exemple l'arbre:

   5
 3   7
1 2 6 9

aurait aussitôt d'impression:

1 2 3 5 6 7 9

maintenant, au lieu d'imprimer le noeud, nous pouvons garder la trace de la valeur précédente dans la séquence dans l'ordre et la comparer à la valeur du noeud courant. Si la valeur du noeud courant est plus petite que la valeur précédente, cela signifie que la séquence n'est pas dans l'Ascendant ordre trié et que la propriété de la BST est violée.

Par exemple, l'arborescence:

   5
 3   7
1 8 6 9

A une violation. Le droit de l'enfant de 3 8 et ce serait ok si 3 était le noeud racine. Cependant, dans un BST 8 finirait comme un enfant de 9 et non pas comme un enfant 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());
}

Les dans l'ordre traversal pour l'arbre échantillon échouerait la vérification pour le noeud 5 depuis le précédent dans l'ordre de 5 8, qui est plus grande donc la propriété DE BST est violée.

4
répondu nem035 2016-01-17 06:26:21
    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 solution alternative pour résoudre ce problème.. similaire avec votre code

2
répondu Zzz... 2014-02-04 18:33:12

un arbre de recherche binaire a les propriétés suivantes où la clé pour le noeud gauche doit être <= la clé du noeud racine et la clé du noeud droit doit être plus grande que la racine.

donc le problème que nous avons est que si les clés dans l'arbre ne sont pas uniques et qu'une traversée dans l'ordre a été faite, nous pourrions obtenir une situation de deux traversées dans l'ordre produisant la même séquence, où 1 serait un TSB valide et l'autre pas, cela se produirait si nous avions un arbre où le noeud de gauche = racine (TSB valide) et le noeud droit = root (invalide pas un TSB).

pour contourner cela, nous avons besoin de maintenir une plage min/max valide entre laquelle la clé "visitée" doit se trouver, et nous passons cette plage comme nous le faisons à d'autres noeuds.

#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
répondu gilla07 2015-01-10 12:33:36

cela n'a pas vraiment de sens de retourner entier.MIN, ENTIER.MAX comme valeurs pour un arbre vide. Peut-être utiliser un entier et retourner null à la place.

0
répondu monkjack 2011-01-01 19:59:28
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
répondu kireet 2014-06-15 21:33:50

nous faisons une marche en profondeur à travers l'arbre, testant la validité de chaque noeud au fur et à mesure. Un noeud donné est valide s'il est plus grand que tous les noeuds ancestraux qu'il est dans le sous-arbre droit et moins que tous les noeuds ancestraux qu'il est dans le sous-arbre gauche de. Au lieu de garder la trace de chaque ancêtre pour vérifier ces inégalités, nous vérifions juste le plus grand nombre il doit être plus grand que (son lowerBound) et le plus petit nombre il doit être moins que (son upperBound).

 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
répondu CHANTAL COX 2016-02-15 19:45:52