In Order Nachfolger in binärer Suchbaum

stimmen
20

Bei einem gegebenen Knoten in einem BST, wie findet man den nächst höheren Schlüssel?

Veröffentlicht am 29/03/2011 um 12:25
quelle vom benutzer
In anderen Sprachen...                            


16 antworten

stimmen
2

Schauen Sie sich hier: inOrder Nachfolger in einem binären Suchbaum

In Binary Tree, Inorder Nachfolger eines Knotens ist der nächste Knoten in Inorder Traversal des Binary Tree. Inorder Nachfolger ist für den letzten Knoten in Inoorder traversal NULL. In binärer Suchbaum, Inorder Nachfolger eines Eingangsknotens kann auch als Knoten mit dem kleinsten Schlüssel größer als der Schlüssel des Eingangsknotens definiert werden.

Beantwortet am 29/03/2011 um 12:28
quelle vom benutzer

stimmen
64

Die allgemeine Art und Weise hängt davon ab, ob Sie einen übergeordneten Link in Ihrem Knoten haben oder nicht.

Wenn Sie den Link Elternteil speichern

Dann wählen Sie:

  1. Das linke Kind des rechten Kindes, wenn Ihre aktuelle Knoten hat ein Recht Kind. Wenn das rechte Kind kein linkes Kind hat das Recht, Kind ist Ihr Inorder Nachfolger.
  2. Navigieren Sie durch die Eltern Vorfahren Knoten auf, und wenn Sie ein Elternteil, dessen linkes Kind finden, ist der Knoten, den Sie zur Zeit befinden sich auf der Eltern ist die Inorder Nachfolger des ursprünglichen Knotens.

Wenn Sie mit dem rechten Kind haben, tun, diesen Ansatz (Fall 1 oben):

inorder-when-rechts-Kind

Wenn Sie noch kein Recht Kind haben, tun diesen Ansatz (Fall 2 oben):

inorder-wenn-no-rechts-Kind

Wenn Sie nicht speichern den übergeordneten Link

Dann müssen Sie einen kompletten Scan des Baumes laufen, den Knoten zu verfolgen, in der Regel mit einem Stapel, so dass Sie die Informationen, die notwendig, um im Grunde das gleiches tun wie die erste Methode, die auf dem übergeordneten Link verlassen.

Beantwortet am 29/03/2011 um 12:47
quelle vom benutzer

stimmen
2

Hier ist eine Implementierung ohne die Notwendigkeit für Eltern Links oder Zwischenstrukturen (wie ein Stapel). Diese in Ordnung ist Nachfolgerfunktion ein bisschen anders zu dem, was die meisten könnte gesucht werden, da sie arbeitet nach dem Schlüssel zu dem Knoten gegenüber. Auch wird es einen Nachfolger eines Schlüssels finden, auch wenn es nicht in dem Baum ist. Nicht zu schwer zu ändern, wenn Sie benötigen jedoch.

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));
    }
}
}
Beantwortet am 27/04/2012 um 15:47
quelle vom benutzer

stimmen
2

Mit binärer Suchbaum zu finden, der Algorithmus die nächsthöhere Knoten eines bestimmten Knotens im Grunde ist die niedrigste Knoten des rechten Unterbaum dieses Knotens zu finden.

Der Algorithmus kann nur einfach sein:

  1. Beginnen Sie mit dem rechten Kind des gegebenen Knotens (macht es den temporäre Stromknoten)
  2. Wenn der aktuelle Knoten kein linkes Kind hat, ist es die nächsthöhere Knoten.
  3. Wenn der aktuelle Knoten ein linkes Kind hat, machen es der aktuelle Knoten.

2 und 3 wiederholen, bis wir nächst höheren Knoten finden.

Beantwortet am 02/11/2012 um 20:13
quelle vom benutzer

stimmen
4

Python - Code zu der wichtigsten Lasse Antwort :

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
Beantwortet am 12/01/2013 um 23:25
quelle vom benutzer

stimmen
1

C ++ Lösung Knoten hat links, rechts, und Abstammungszeiger unter der Annahme:

Dies verdeutlicht die Funktion , Node* getNextNodeInOrder(Node)die die nächste Taste des binären Suchbaum in Ordnung zurückkehrt.

#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;
}

Welche Drucke:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Beantwortet am 16/07/2013 um 19:21
quelle vom benutzer

stimmen
0

Sie können weitere Informationen lesen Sie hier (Rus Lunge)

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
Beantwortet am 07/10/2014 um 11:25
quelle vom benutzer

stimmen
0

Diese Antworten scheinen alle zu kompliziert für mich. Wir brauchen wirklich keine Abstammungszeiger oder jegliche Hilfsdatenstrukturen wie ein Stapel. Alles, was wir tun müssen, ist, den Baum von der Wurzel in Ordnung, eine Fahne so schnell eingestellt durchquert, wie wir den Zielknoten und den nächsten Knoten im Baum, die wir besuchen werden die um Nachfolgeknoten zu finden. Hier ist eine schnelle und schmutzige Routine, die ich schrieb auf.

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);
}
Beantwortet am 09/12/2014 um 05:29
quelle vom benutzer

stimmen
1

Wenn wir ein, um Traversal führen Sie dann besuchen wir den linken Unterbaum, dann Wurzelknoten und schließlich den rechten Teilbaum für jeden Knoten im Baum. Durchführen eines um Traversal gibt uns die Schlüssel eines binären Suchbaumes in aufsteigender Reihenfolge, so dass, wenn wir verweisen die um Nachfolger eines Knotens der Zugehörigkeit zu einem binären Suchbaum Abrufen wir meinen, was der nächste Knoten in der Folge wäre aus der gegebene Knoten.

Lets sagen, dass wir einen Knoten R haben, und wir wollen seine um Nachfolger würden wir die folgenden Fälle haben.

[1] Die Wurzel R hat einen richtigen Knoten, so alles , was wir tun müssen , ist auf der linken Seite die meisten Knoten der R-> rechts zu überqueren.

[2] Die Wurzel R hat keinen rechten Knoten, in diesem Fall haben wir die übergeordneten Verknüpfungen folgenden auf den Baum durchlaufen zurück , bis der Knoten R ein linkes Kind seiner Eltern ist, wenn dies der Fall wir den übergeordneten Knoten P als um Nachfolger haben , .

[3] Wir sind am äußersten rechten Knoten des Baumes, in diesem Fall gibt es keine , um Nachfolger ist.

Die Umsetzung wird auf die folgenden Knotendefinition basiert

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);
}
Beantwortet am 10/01/2015 um 20:11
quelle vom benutzer

stimmen
0

JavaScript-Lösung - Wenn der gegebene Knoten einen rechten Knoten hat, dann wieder den kleinsten Knoten im rechten Teilbaum - Wenn nicht, dann gibt es zwei Möglichkeiten: - Der angegebene Knoten ein linkes Kind des Elternknotens ist. Wenn dem so ist, zurückkehren den übergeordneten Knoten. Ansonsten ist der gegebene Knoten ein rechtes Kind des Elternknotens. Wenn ja, schicken Sie das rechte Kind des Elternknotens

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;
  }
}
Beantwortet am 19/10/2015 um 03:44
quelle vom benutzer

stimmen
0

Dadurch in 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);
    }
}
Beantwortet am 22/11/2016 um 04:58
quelle vom benutzer

stimmen
0

Wir können diese teilen in drei Fällen:

  1. Wenn der Knoten ein Elternteil ist: In diesem Fall finden wir, wenn es einen richtigen Knoten hat und auf das äußerste linke Kind des rechten Knoten durchqueren. Falls der richtige Knoten keine Kinder dann der rechte Knoten sein Inorder Nachfolger ist. Wenn es keine richtigen Knoten ist, müssen wir den Baum nach oben zu dem Inorder Nachfolger zu finden.

  2. Wenn der Knoten ein linkes Kind ist: In diesem Fall ist die Mutter der Inorder Nachfolger.

  3. Wenn der Knoten (nennen wir es x) ein rechtes Kind ist (der unmittelbar übergeordneten): Wir durchqueren den Baum, bis wir einen Knoten, dessen linken Unterbaum hat x finden.

Extremfall: Wenn der Knoten der äußerste rechte Ecke Knoten ist, gibt es keinen Inorder Nachfolger.

Beantwortet am 30/11/2016 um 10:12
quelle vom benutzer

stimmen
0

Jedes „Tutorial“ , die ich auf Google und alle Antworten in diesem Thread überprüft verwendet die folgende Logik: " Wenn der Knoten ein rechtes Kind nicht , dann haben seine in Ordnung Nachfolger eines seiner Vorfahren sein Mit Link Eltern halten unterwegs bis. Sie erhalten den Knoten, der das linke Kind seiner Eltern ist. Dann ist dieser übergeordnete Knoten der in Ordnung Nachfolger sein wird. "

Dies ist das gleiche wie „denken , wenn meine Eltern größer als ich ist, dann bin ich das linke Kind “ (Eigenschaft eines binären Suchbaum). Das bedeutet , dass Sie einfach die Elternkette gehen , bis die obige Eigenschaft wahr ist. Was meiner Meinung nach ergibt sich ein eleganter Code.

Ich denke , den Grund , warum jede Überprüfung „ Ich ist das linke Kind “ von anstelle von Werten im Codepfad in den Filialen suchen , die von „Borgen“ Logik von dem no-link-to-Eltern - Algorithmus kommt Mutter Links verwendet.

Auch aus dem Code unten enthalten wir es sehen keine Notwendigkeit für die Strukturstapeldaten wie von anderen Antworten.

Folgende ist eine einfache C ++ Funktion, die für beide Anwendungsfälle (mit und ohne Verwendung der Link zum parent) funktioniert.

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;
    }
}
Beantwortet am 01/01/2017 um 13:11
quelle vom benutzer

stimmen
0

C # -Implementierung (Non rekursiv!), Um die ‚next‘ Knoten eines bestimmtes Knotens in einem binären Suchbaum zu finden, wo jeder Knoten einen Link zu seinen Eltern hat.

    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);
    }
Beantwortet am 16/03/2017 um 07:15
quelle vom benutzer

stimmen
0

Wir können die Nachfolger in O (log n) ohne Abstammungszeiger mit (für einen ausgeglichenen Baum).

Die Idee ist sehr ähnlich, wenn Sie Abstammungszeiger haben.

Wir können eine rekursive Funktion definieren, die dies erreicht, wie folgt:

  • Wenn der aktuelle Knoten das Ziel ist, kehren die am weitesten links / kleinste Knoten seiner rechten Teilbaum, wenn es vorhanden ist.
  • Recurse links, wenn das Ziel kleiner ist als der aktuelle Knoten ist, und richtig, wenn es größer ist.
  • Wenn das Ziel auf der linken Seite, und wir haben keinen Nachfolger noch, geben Sie den aktuellen Knoten gefunden.

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

Live - Java - Demo .

Beantwortet am 31/12/2017 um 16:10
quelle vom benutzer

stimmen
1

wir nicht Mutter Link benötigen oder stapeln die um Nachfolger in O (log n) (unter der Annahme, ausgewogenen Baum) zu finden. Halten Sie eine temporäre Variable mit dem letzten Wert in der Inorder Traversal angetroffen, der größer ist als der Schlüssel ist. wenn Inorder Traversal feststellt, dass der Knoten nicht ein rechtes Kind hat, dann wäre dies der Inorder Nachfolger sein. der linke Abkömmling des rechten Kindes sonst.

Beantwortet am 03/07/2018 um 20:07
quelle vom benutzer

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