Dans Successeur Ordre binaire Rechercher Arbre

voix
20

Compte tenu d'un noeud dans un BST, comment peut-on trouver la prochaine clé supérieure?

Créé 29/03/2011 à 12:25
source utilisateur
Dans d'autres langues...                            


16 réponses

voix
2

Consultez ici: Successeur afinde dans un arbre de recherche binaire

Dans Binary Tree, successeur Inorder d'un nœud est le nœud suivant dans Inorder traversal de l'arbre binaire. Afinde Successeur est NULL pour le dernier nœud dans Inoorder traversal. Dans Binary Recherche Arbre, successeur Inorder d'un noeud d'entrée peut également être défini comme le noeud avec la plus petite clé supérieure à la clé du noeud d'entrée.

Créé 29/03/2011 à 12:28
source utilisateur

voix
64

La manière générale dépend si vous avez un lien parent dans vos nœuds ou non.

Si vous enregistrez le lien parent

Ensuite, vous choisissez:

  1. L'enfant de l'extrême gauche à droite enfant, si votre nœud actuel a un enfant droit. Si l'enfant n'a pas droit enfant gauche, l'enfant droite est votre successeur infixe.
  2. Naviguer dans les nœuds ancêtres des parents, et quand vous trouvez un parent dont l'enfant gauche est le nœud que vous êtes actuellement, le parent est le successeur de envue de votre nœud d'origine.

Si vous avez droit de l'enfant, faire cette approche (cas 1 ci-dessus):

afinde-en-droit enfant

Si vous ne disposez pas d'un droit de l'enfant, faire cette approche (cas 2 ci-dessus):

afinde-quand-no-droit enfant

Si vous ne stockez pas le lien parent

Ensuite, vous devez lancer un balayage complet de l'arbre, en gardant une trace des noeuds, généralement avec une pile, de sorte que vous avez les informations nécessaires pour faire essentiellement la même chose que la première méthode qui reposait sur le lien parent.

Créé 29/03/2011 à 12:47
source utilisateur

voix
2

Voici une mise en œuvre sans avoir besoin de liens parents ou des structures intermédiaires (comme une pile). Cette fonction successeur en ordre est un peu différent de ce que la plupart pourrait être à la recherche puisqu'il fonctionne sur la clé, par opposition au nœud. En outre, il trouvera un successeur d'une clé, même si elle n'est pas présent dans l'arbre. Pas trop difficile de changer si vous deviez cependant.

public class Node<T extends Comparable<T>> {

private T data;
private Node<T> left;
private Node<T> right;

public Node(T data, Node<T> left, Node<T> right) {
    this.data = data;
    this.left = left;
    this.right = right;
}

/*
 * Returns the left-most node of the current node. If there is no left child, the current node is the left-most.
 */
private Node<T> getLeftMost() {
    Node<T> curr = this;
    while(curr.left != null) curr = curr.left;
    return curr;
}

/*
 * Returns the right-most node of the current node. If there is no right child, the current node is the right-most.
 */
private Node<T> getRightMost() {
    Node<T> curr = this;
    while(curr.right != null) curr = curr.right;
    return curr;
}

/**
 * Returns the in-order successor of the specified key.
 * @param key The key.
 * @return
 */
public T getSuccessor(T key) {
    Node<T> curr = this;
    T successor = null;
    while(curr != null) {
        // If this.data < key, search to the right.
        if(curr.data.compareTo(key) < 0 && curr.right != null) {
            curr = curr.right;
        }
        // If this.data > key, search to the left.
        else if(curr.data.compareTo(key) > 0) { 
            // If the right-most on the left side has bigger than the key, search left.
            if(curr.left != null && curr.left.getRightMost().data.compareTo(key) > 0) {
                curr = curr.left;
            }
            // If there's no left, or the right-most on the left branch is smaller than the key, we're at the successor.
            else {
                successor = curr.data;
                curr = null;
            }
        }
        // this.data == key...
        else {
            // so get the right-most data.
            if(curr.right != null) {
                successor = curr.right.getLeftMost().data;
            }
            // there is no successor.
            else {
                successor = null;
            }
            curr = null;
        }
    }
    return successor;
}

public static void main(String[] args) {
    Node<Integer> one, three, five, seven, two, six, four;
    one = new Node<Integer>(Integer.valueOf(1), null, null);
    three = new Node<Integer>(Integer.valueOf(3), null, null);
    five = new Node<Integer>(Integer.valueOf(5), null, null);
    seven = new Node<Integer>(Integer.valueOf(7), null, null);
    two = new Node<Integer>(Integer.valueOf(2), one, three);
    six = new Node<Integer>(Integer.valueOf(6), five, seven);
    four = new Node<Integer>(Integer.valueOf(4), two, six);
    Node<Integer> head = four;
    for(int i = 0; i <= 7; i++) {
        System.out.println(head.getSuccessor(i));
    }
}
}
Créé 27/04/2012 à 15:47
source utilisateur

voix
2

Avec Binary Search Arbre, l'algorithme pour trouver le plus élevé suivant le noeud d'un noeud donné est de trouver le plus bas essentiellement nœud du sous-arbre droit de ce nœud.

L'algorithme peut juste être simplement:

  1. Commencez avec l'enfant droit du nœud donné (en faire le noeud courant temporaire)
  2. Si le nœud actuel n'a pas d'enfant à gauche, il est le prochain nœud le plus élevé.
  3. Si le nœud actuel a un enfant à gauche, faire le nœud courant.

Répétez 2 et 3 jusqu'à ce que nous trouvons à côté nœud le plus élevé.

Créé 02/11/2012 à 20:13
source utilisateur

voix
4

Code Python du Lasse réponse :

def findNext(node):
  if node.rightChild != None:
    return findMostLeft(node.rightChild)
  else:
    parent = node.parent
    while parent != None:
      if parent.leftChild == node:
        break
      node = parent
      parent = node.parent
    return parent
Créé 12/01/2013 à 23:25
source utilisateur

voix
1

C ++ solution en supposant les noeuds ont gauche, à droite, et les pointeurs de parents:

Ceci illustre la fonction Node* getNextNodeInOrder(Node)qui renvoie la clé suivante de l'arbre de recherche binaire dans l'ordre.

#include <cstdlib>
#include <iostream>
using namespace std;

struct Node{
    int data;
    Node *parent;
    Node *left, *right;
};

Node *createNode(int data){
    Node *node =  new Node();
    node->data = data;
    node->left = node->right = NULL;
    return node;
}

Node* getFirstRightParent(Node *node){
    if (node->parent == NULL)
        return NULL;

    while (node->parent != NULL && node->parent->left != node){
        node = node->parent;
    }
    return node->parent;
}
Node* getLeftMostRightChild(Node *node){
    node = node->right;
    while (node->left != NULL){
        node = node->left;
    }
    return node;
}
Node *getNextNodeInOrder(Node *node){
    //if you pass in the last Node this will return NULL
    if (node->right != NULL)
        return getLeftMostRightChild(node);
    else
        return getFirstRightParent(node);
}
void inOrderPrint(Node *root)
{
    if (root->left != NULL) inOrderPrint(root->left);
    cout << root->data << " ";
    if (root->right != NULL) inOrderPrint(root->right);
}

int main(int argc, char** argv) {
    //Purpose of this program is to demonstrate the function getNextNodeInOrder
    //of a binary tree in-order.  Below the tree is listed with the order
    //of the items in-order.  1 is the beginning, 11 is the end.  If you 
    //pass in the node 4, getNextNode returns the node for 5, the next in the 
    //sequence.

    //test tree:
    //
    //        4
    //      /    \
    //     2      11
    //    / \     /
    //   1  3    10
    //          /
    //         5
    //          \
    //           6 
    //            \
    //             8
    //            / \
    //           7  9


    Node *root = createNode(4);
    root->parent = NULL;

    root->left = createNode(2);
    root->left->parent = root;

    root->right = createNode(11);
    root->right->parent = root;

    root->left->left = createNode(1);
    root->left->left->parent = root->left;

    root->right->left = createNode(10);
    root->right->left->parent = root->right;

    root->left->right = createNode(3);
    root->left->right->parent = root->left;

    root->right->left->left = createNode(5);
    root->right->left->left->parent = root->right->left;

    root->right->left->left->right = createNode(6);
    root->right->left->left->right->parent = root->right->left->left;

    root->right->left->left->right->right = createNode(8);
    root->right->left->left->right->right->parent = 
            root->right->left->left->right;

    root->right->left->left->right->right->left = createNode(7);
    root->right->left->left->right->right->left->parent = 
            root->right->left->left->right->right;

    root->right->left->left->right->right->right = createNode(9);
    root->right->left->left->right->right->right->parent = 
            root->right->left->left->right->right;

    inOrderPrint(root);

    //UNIT TESTING FOLLOWS

    cout << endl << "unit tests: " << endl;

    if (getNextNodeInOrder(root)->data != 5)
        cout << "failed01" << endl;
    else
        cout << "passed01" << endl;

    if (getNextNodeInOrder(root->right) != NULL)
        cout << "failed02" << endl;
    else
        cout << "passed02" << endl;

    if (getNextNodeInOrder(root->right->left)->data != 11)
        cout << "failed03" << endl;
    else
        cout << "passed03" << endl;

    if (getNextNodeInOrder(root->left)->data != 3)
        cout << "failed04" << endl;
    else
        cout << "passed04" << endl;

    if (getNextNodeInOrder(root->left->left)->data != 2)
        cout << "failed05" << endl;
    else
        cout << "passed05" << endl;

    if (getNextNodeInOrder(root->left->right)->data != 4)
        cout << "failed06" << endl;
    else
        cout << "passed06" << endl;

    if (getNextNodeInOrder(root->right->left->left)->data != 6)
        cout << "failed07" << endl;
    else
        cout << "passed07" << endl;

    if (getNextNodeInOrder(root->right->left->left->right)->data != 7)
        cout << "failed08 it came up with: " << 
          getNextNodeInOrder(root->right->left->left->right)->data << endl;
    else
        cout << "passed08" << endl;

    if (getNextNodeInOrder(root->right->left->left->right->right)->data != 9)
        cout << "failed09 it came up with: " 
          << getNextNodeInOrder(root->right->left->left->right->right)->data 
          << endl;
    else
        cout << "passed09" << endl;

    return 0;
}

Qui imprime:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Créé 16/07/2013 à 19:21
source utilisateur

voix
0

Vous pouvez lire des informations supplémentaires ici (poumon Rus)

Node next(Node x)
   if x.right != null
      return minimum(x.right)
   y = x.parent
   while y != null and x == y.right
      x = y
      y = y.parent
   return y


Node prev(Node x)
   if x.left != null
      return maximum(x.left)
   y = x.parent
   while y != null and x == y.left
      x = y
      y = y.parent
   return y
Créé 07/10/2014 à 11:25
source utilisateur

voix
0

Ces réponses semblent tous trop compliqué pour moi. Nous avons vraiment pas besoin des pointeurs parents ou des structures de données auxiliaires comme une pile. Tout ce que nous devons faire est de parcourir l'arbre de la racine dans l'ordre, définir un indicateur dès que nous trouvons le nœud cible, et le nœud suivant dans l'arbre que l'on visite sera le successeur dans le nœud de commande. Voici une routine rapide et sale j'ai écrit.

Node* FindNextInorderSuccessor(Node* root, int target, bool& done)
{
    if (!root)
        return NULL;

    // go left
    Node* result = FindNextInorderSuccessor(root->left, target, done);
    if (result)
        return result;

    // visit
    if (done)
    {
        // flag is set, this must be our in-order successor node
        return root;
    }
    else
    {
        if (root->value == target)
        {
            // found target node, set flag so that we stop at next node
            done = true;
        }
    }

    // go right
    return FindNextInorderSuccessor(root->right, target, done);
}
Créé 09/12/2014 à 05:29
source utilisateur

voix
1

Si nous effectuons une dans l'ordre traversal nous visitons la sous-arborescence à gauche, puis nœud racine et enfin le sous-arbre droit pour chaque nœud dans l'arborescence. Réalisation d'un pour traversal nous donner les clés d'un arbre de recherche binaire dans l'ordre croissant, alors quand on se réfère à la récupération de l'en successeur de l'ordre d'un nœud appartenant à un arbre de recherche binaire, nous entendons ce serait le nœud suivant dans la séquence de le noeud donné.

Disons que nous avons un noeud R et nous voulons son successeur dans l'ordre nous aurions les cas suivants.

[1] La racine R a un nœud droit, donc tout ce que nous devons faire est de traverser vers le nœud le plus à gauche de R> droite.

[2] La racine R n'a pas nœud droit, dans ce cas , on traverse de nouveau l'arbre en suivant les liens parents jusqu'à ce que le noeud R est un enfant gauche de son parent, lorsque cela se produit , nous avons le nœud parent P comme dans le successeur de l' ordre .

[3] Nous sommes au nœud extrême droite de l'arbre, dans ce cas , il n'y a en successeur de l' ordre.

La mise en œuvre est basée sur la définition du noeud suivant

class node
{
private:
node* left;
node* right;
node* parent
int data;

public:
//public interface not shown, these are just setters and getters
.......
};

//go up the tree until we have our root node a left child of its parent
node* getParent(node* root)
{
    if(root->parent == NULL)
        return NULL;

    if(root->parent->left == root)
        return root->parent;
    else
        return getParent(root->parent);
}

node* getLeftMostNode(node* root)
{
    if(root == NULL)
        return NULL;

    node* left = getLeftMostNode(root->left);
    if(left)
        return left;
    return root;
}

//return the in order successor if there is one.
//parameters - root, the node whose in order successor we are 'searching' for
node* getInOrderSucc(node* root)
{
    //no tree, therefore no successor
    if(root == NULL)
        return NULL;

    //if we have a right tree, get its left most node
    if(root->right)
        return getLeftMostNode(root->right);
    else
        //bubble up so the root node becomes the left child of its
        //parent, the parent will be the inorder successor.
        return getParent(root);
}
Créé 10/01/2015 à 20:11
source utilisateur

voix
0

solution JavaScript - Si le nœud donné a un noeud à droite, puis retourner le plus petit nœud dans le sous-arbre droit - Sinon, il y a 2 possibilités: - Le nœud donné est un enfant gauche du nœud parent. Si oui, retourner le nœud parent. Dans le cas contraire, le noeud donné est un enfant droit du nœud parent. Dans ce cas, le retour de l'enfant droit du nœud parent

function nextNode(node) {
  var nextLargest = null;
  if (node.right != null) {
    // Return the smallest item in the right subtree

    nextLargest = node.right;
    while (nextLargest.left !== null) {
      nextLargest = nextLargest.left;
    }

    return nextLargest;
  } else {
    // Node is the left child of the parent
    if (node === node.parent.left) return node.parent;

    // Node is the right child of the parent
    nextLargest = node.parent;
    while (nextLargest.parent !== null && nextLargest !== nextLargest.parent.left) {
      nextLargest = nextLargest.parent
    }
    return nextLargest.parent;
  }
}
Créé 19/10/2015 à 03:44
source utilisateur

voix
0

Faire cela en Java

TreeNode getSuccessor(TreeNode treeNode) {
    if (treeNode.right != null) {
         return getLeftMostChild(treeNode.right);
    } else {
        TreeNode p = treeNode.parent;
        while (p != null && treeNode == p.right) { // traverse upwards until there is no parent (at the last node of BST and when current treeNode is still the parent's right child
            treeNode = p;
            p = p.parent; // traverse upwards
        }
        return p; // returns the parent node
    }
}

TreeNode getLeftMostChild(TreeNode treeNode) {
    if (treeNode.left == null) {
        return treeNode;
    } else {
        return getLeftMostChild(treeNode.left);
    }
}
Créé 22/11/2016 à 04:58
source utilisateur

voix
0

On peut diviser ce dans 3 cas:

  1. Si le nœud est un parent: Dans ce cas, nous trouvons si elle a un noeud à droite et traverser à l'extrême gauche enfant du nœud droit. Dans le cas où le nœud droit n'a pas d'enfant alors le nœud droit est son successeur infixe. S'il n'y a pas de noeud droite, nous devons déplacer l'arbre pour trouver le successeur afinde.

  2. Si le nœud est un enfant gauche: Dans ce cas, le parent est le successeur infixe.

  3. Si le nœud (appeler x) est un droit de l'enfant (de son parent immédiat): Nous traversons l'arbre jusqu'à ce qu'on trouve un nœud dont le sous-arbre gauche a x.

Cas extrême: Si le nœud est le nœud de coin à droite, il n'y a pas de successeur infixe.

Créé 30/11/2016 à 10:12
source utilisateur

voix
0

Chaque « tutoriel » que j'ai vérifié sur Google et toutes les réponses dans ce fil utilise la logique suivante: « Si le nœud ne dispose pas d' un enfant tout de suite son successeur en ordre sera l' un de ses ancêtres utilisant le lien parent continuer à voyager jusqu'à. vous obtenez le noeud qui est l'enfant gauche de son parent. Ensuite , ce nœud parent sera le successeur dans l'ordre. "

Ceci est la même chose que la pensée « si mon parent est plus grand que moi, je suis l'enfant gauche » (propriété d'un arbre de recherche binaire). Cela signifie que vous pouvez simplement marcher jusqu'à la chaîne mère jusqu'à ce que la propriété ci - dessus est vrai. Ce qui dans mes résultats d'opinion dans un code plus élégant.

Je suppose que la raison pour laquelle tout le monde vérifie « suis - je l'enfant gauche » en regardant les branches au lieu de valeurs dans le chemin de code qui utilise des liens parent vient de la logique « d'emprunt » de la non-link-to-parent algorithme.

En outre du code inclus ci - dessous , nous pouvons voir qu'il est pas nécessaire pour la structure de données de la pile comme suggéré par d' autres réponses.

Ce qui suit est simple fonction C ++ qui fonctionne pour les deux cas d'utilisation (avec et sans utiliser le lien parent).

Node* nextInOrder(const Node *node, bool useParentLink) const
{
    if (!node)
        return nullptr;

    // when has a right sub-tree
    if (node->right) {
        // get left-most node from the right sub-tree
        node = node->right;
        while (node->left)
            node = node->left;
        return node;
    }

    // when does not have a right sub-tree
    if (useParentLink) {
        Node *parent = node->parent;
        while (parent) {
            if (parent->value > node->value)
                return parent;
            parent = parent->parent;
        }
        return nullptr;
    } else {
        Node *nextInOrder = nullptr;
        // 'root' is a class member pointing to the root of the tree
        Node *current = root;
        while (current != node) {
            if (node->value < current->value) {
                nextInOrder = current;
                current = current->left;
            } else {
                current = current->right;
            }
        }
        return nextInOrder;
    }
}

Node* previousInOrder(const Node *node, bool useParentLink) const
{
    if (!node)
        return nullptr;

    // when has a left sub-tree
    if (node->left) {
        // get right-most node from the left sub-tree
        node = node->left;
        while (node->right)
            node = node->right;
        return node;
    }

    // when does not have a left sub-tree
    if (useParentLink) {
        Node *parent = node->parent;
        while (parent) {
            if (parent->value < node->value)
                return parent;
            parent = parent->parent;
        }
        return nullptr;
    } else {
        Node *prevInOrder = nullptr;
        // 'root' is a class member pointing to the root of the tree
        Node *current = root;
        while (current != node) {
            if (node->value < current->value) {
                current = current->left;
            } else {
                prevInOrder = current;
                current = current->right;
            }
        }
        return prevInOrder;
    }
}
Créé 01/01/2017 à 13:11
source utilisateur

voix
0

C # mise en œuvre de (non récursif!) Pour trouver le noeud « suivant » d'un noeud donné dans un arbre de recherche binaire où chaque noeud a un lien vers son parent.

    public static Node WhoIsNextInOrder(Node root, Node node)
    {
        if (node.Right != null)
        {
            return GetLeftMost(node.Right);
        }
        else
        {
            Node p = new Node(null,null,-1);
            Node Next = new Node(null, null, -1);
            bool found = false;
            p = FindParent(root, node);
            while (found == false)
                {
                    if (p.Left == node) { Next = p; return Next; }
                    node = p;
                    p = FindParent(root, node);
                }
            return Next;
        }
    }

    public static Node FindParent(Node root, Node node)
    {
        if (root == null || node == null)
        {
            return null;
        }
        else if ( (root.Right != null && root.Right.Value == node.Value) || (root.Left != null && root.Left.Value == node.Value))
        {
            return root;
        }
        else
        {
            Node found = FindParent(root.Right, node);

            if (found == null)
            {
                found = FindParent(root.Left, node);
            }

            return found;
        }
    }

    public static Node GetLeftMost (Node node)
    {
        if (node.Left == null)
        {
            return node;
        }
        return GetLeftMost(node.Left);
    }
Créé 16/03/2017 à 07:15
source utilisateur

voix
0

Nous pouvons trouver le successeur O (log n) sans utiliser des pointeurs de parents (pour un arbre équilibré).

L'idée est très similaire à quand vous avez des pointeurs de parents.

Nous pouvons définir une fonction récursive qui permet d'atteindre cela comme suit:

  • Si le nœud actuel est la cible, retourner le plus à gauche / petit nœud de son sous-arbre droit, si elle existe.
  • Recurse gauche si la cible est plus petite que le nœud actuel, et à droite si elle est supérieure.
  • Si la cible est à gauche et on n'a pas encore trouvé un successeur, retourner le nœud actuel.

Pseudo-code:

Key successor(Node current, Key target):
   if current == null
      return null
   if target == current.key
      if current.right != null
         return leftMost(current.right).key
      else
         return specialKey
   else
      if target < current.key
         s = successor(current.left, target)
         if s == specialKey
            return current.key
         else
            return s
      else
         return successor(current.right, target)

Node leftMost(Node current):
    while current.left != null
       current = current.left
    return current

Java démo en direct .

Créé 31/12/2017 à 16:10
source utilisateur

voix
1

nous ne avez pas besoin de lien parent ou pile pour trouver le successeur en ordre O (log n) (en supposant arbre équilibré). Gardez une variable temporaire avec la valeur la plus récente rencontrée dans le parcours infixe qui est plus grande que la clé. si afinde traversal constate que le nœud ne dispose pas d'un droit de l'enfant, alors ce serait le successeur infixe. d'autre, le descendant de gauche à droite l'enfant.

Créé 03/07/2018 à 20:07
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more