A rendelés utód bináris keresési fa

szavazat
20

Adott egy csomópont egy BST, hogyan lehet megtalálni a következő magasabb kulcs?

A kérdést 29/03/2011 12:25
a forrás felhasználó
Más nyelveken...                            


16 válasz

szavazat
2

Nézze meg itt: Inorder utódja bináris kereső fába

A bináris fa, Inorder utódja a csomópont a következő csomópont Inorder bejárását a bináris fában. Inorder utód NULL az utolsó csomópont Inoorder bejárás. A bináris keresés Tree Inorder utóda bemeneti csomópontot is definiálható, mint a csomópont a legkisebb kulcs nagyobb, mint a legfontosabb bemeneti csomóponton.

Válaszolt 29/03/2011 12:28
a forrás felhasználó

szavazat
64

Az általános módja attól függ, hogy van-e a szülő linket a csomópontok vagy sem.

Ha tárolni a szülő kapcsolat

Akkor vedd:

  1. A bal oldali gyermek a jobb gyermek, ha az aktuális csomópont joga van gyermeke. Ha a jobb oldali gyermek nem baloldali gyermek, a jobb gyermek a inorder utódja.
  2. Ugrás fel a szülő őse csomópontok, és ha talál egy szülő, akinek a bal gyermek a csomópont maga jelenleg a szülő az inorder utódja az eredeti csomópontra.

Ha van jobb fia, tegye ezt a megközelítést (1. eset fent):

inorder-ha-right-gyermek

Ha nincs jobb gyerek, akkor ez a megközelítés (2. eset fent):

inorder-ha-nem-right-gyermek

Ha nem tárolja a szülő kapcsolat

Akkor meg kell futtatni egy teljes scan a fa, nyomon követése a csomópontok, általában egy halom, úgy, hogy a szükséges információk alapvetően nem ugyanaz, mint az első módszer, hogy hivatkozott a szülő link.

Válaszolt 29/03/2011 12:47
a forrás felhasználó

szavazat
2

Itt egy végrehajtási nélkül a szülő kapcsolat vagy köztes struktúrák (mint egy köteg). Ez rendű utódja funkció egy kicsit más, mint amit a legtöbb lehet, hogy keres, mert működik a kulcs, szemben a csomópontot. Is, akkor utódot találni a kulcsot akkor is, ha nincs jelen a fán. Nem túl nehéz változtatni, ha szükséges, de.

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));
    }
}
}
Válaszolt 27/04/2012 15:47
a forrás felhasználó

szavazat
2

A bináris keresés Tree algoritmus, hogy megtalálják a következő legmagasabb csomópont egy adott csomópont alapvetően megtalálni a legalacsonyabb csomópont a jobb részfa a csomóval.

Az algoritmus csak egyszerűen:

  1. Kezdjük a jobb gyerek az adott csomópont (legyen az ideiglenes aktuális csomópont)
  2. Ha az aktuális csomópontnak nincs bal gyerek, akkor a következő legmagasabb csomópontot.
  3. Ha az aktuális csomópont rendelkezik egy bal gyermek, hogy az aktuális csomópont.

Ismételjük a 2. és 3. amíg meg nem találjuk a következő legmagasabb csomópontot.

Válaszolt 02/11/2012 20:13
a forrás felhasználó

szavazat
4

Python kódot a Lasse a válasz :

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
Válaszolt 12/01/2013 23:25
a forrás felhasználó

szavazat
1

C ++ megoldás feltételezve csomópont balra, jobbra, és a szülő mutatók:

Ez jól mutatja a függvény Node* getNextNodeInOrder(Node), amely visszaadja a következő kulcsot a bináris keresési fa in-sorrendben.

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

Melyik nyomatok:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Válaszolt 16/07/2013 19:21
a forrás felhasználó

szavazat
0

Elolvashatja további info itt (Rus tüdő)

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
Válaszolt 07/10/2014 11:25
a forrás felhasználó

szavazat
0

Ezek a válaszok minden túlságosan bonyolultnak tűnnek nekem. Mi tényleg nem kell szülő mutatókat vagy bármilyen kiegészítő adat struktúrákat, mint egy verem. Csak annyit kell tennie, hogy keresztezik a fát a gyökér-order, meg a zászló, amint megtaláljuk a cél csomópont, és a következő a fában, hogy meglátogatjuk lesz ahhoz leszármazott csomópont. Itt van egy gyors és piszkos rutin írtam fel.

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);
}
Válaszolt 09/12/2014 05:29
a forrás felhasználó

szavazat
1

Ha végzünk egy ahhoz bejárás akkor keresse fel a bal részfa, akkor gyökércsomópont és végül a jobb részfa minden csomópont a fa. Végrehajtása érdekében bejárás megadja nekünk a kulcsokat egy bináris keresési fa emelkedő sorrendben, így amikor utalunk visszakeresése érdekében utódja csomópont tartozó bináris kereső fába azt jelenti, hogy mi lenne a következő csomópont a szekvencia az adott csomópont.

Tegyük fel, van egy node R és szeretnénk a annak érdekében, hogy utódja mi lett volna a következő esetekben.

[1] A gyökér R joga csomópont, így minden meg kell tennie, hogy áthalad a bal szélső csomópontja R-> jobb.

[2] A gyökér R nincs joga csomópont, ebben az esetben keresztezik vissza a fa követően a szülő kapcsolat, amíg a csomópont R bal gyermek a szülő, amikor ez bekövetkezik már a szülő csomópont a P a annak érdekében, hogy utódja .

[3] Mi a jobb szélső csomópont a fa, ebben az esetben nincs annak utódja.

A végrehajtás alapja a következő csomópontra meghatározás

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);
}
Válaszolt 10/01/2015 20:11
a forrás felhasználó

szavazat
0

JavaScript megoldás - Ha az adott csomópont joga csomópont, majd térjen vissza a legkisebb csomópontot a jobb részfa - Ha nem, akkor 2 lehetőség van: - A megadott csomópont egy bal gyermek a szülő csomópont. Ha igen, vissza a szülő csomópontot. Ellenkező esetben az adott csomópont egy jobb gyermek a szülő csomópont. Ha igen, akkor vissza a jobb gyermek a szülő csomópont

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;
  }
}
Válaszolt 19/10/2015 03:44
a forrás felhasználó

szavazat
0

Ez persze 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);
    }
}
Válaszolt 22/11/2016 04:58
a forrás felhasználó

szavazat
0

Oszthatjuk ezt a 3 esetben:

  1. Ha a csomópont egy szülő: Ebben az esetben azt látjuk, ha van egy jobb csomópont és áthalad a bal szélső gyermek a jobb csomópont. Abban az esetben, a megfelelő csomópontnak nincs gyerek, akkor a jobb oldali csomópont a inorder utódja. Ha nincs jobb csomópont meg kell mozgatni a fát, hogy megtalálják a inorder utódja.

  2. Ha a csomópont egy bal fia: Ebben az esetben a szülő a inorder utódja.

  3. Ha a csomópont (nevezzük x) egy jobb oldali gyermek (a közvetlen anyavállalatának): Mi áthalad a fát, amíg nem találunk egy csomópont, melynek bal alfában x.

Extrém eset: Ha a csomópont a jobb oldali sarokban csomópont, nincs inorder utódja.

Válaszolt 30/11/2016 10:12
a forrás felhasználó

szavazat
0

Minden „bemutató”, hogy megnéztem a google és az összes válasz ebben a témában használja az alábbi logika: " Ha csomópont nincs joga a gyermek akkor annak a rendelésre utódja lesz az egyik ősei. A szülő kapcsolat folyamatosan utazik ig kap a csomópontot, amely a bal gyermek a szülő. akkor ez szülőcsomópont lesz az in-sorrendben utódja. "

Ez ugyanaz, mint a gondolkodás „ha a szülő nagyobb, mint én, akkor én vagyok a bal gyerek ” (ingatlan egy bináris keresési fa). Ez azt jelenti, hogy egyszerűen csak sétálni a szülő láncba, amíg a fenti tulajdonság igaz. Amely véleményem eredmények sokkal elegánsabb kódot.

Azt hiszem, az ok, amiért mindenki ellenőrzi „ vagyok a bal gyerek ” nézi ágak helyett értékeket a kódot útvonal, amely hasznosítja a szülő kapcsolat jön „hitelfelvétel” logikát a no-link-to-parent algoritmus.

Szintén a benne alábbi kódot látjuk van nincs szükség verem adatszerkezet által javasolt más válaszokat.

A következőkben egy egyszerű C ++ függvény, amely mindkettejük számára hasznos esetben (és anélkül kihasználva a link szülő).

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;
    }
}
Válaszolt 01/01/2017 13:11
a forrás felhasználó

szavazat
0

C # végrehajtás (Nem rekurzív!), Hogy megtalálja a „következő” csomópont egy adott csomópont egy bináris keresési fa, ahol minden egyes csomópont egy link a szülő.

    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);
    }
Válaszolt 16/03/2017 07:15
a forrás felhasználó

szavazat
0

Találunk az utód O (log n) használata nélkül szülő mutatók (a kiegyensúlyozott fa).

Az ötlet nagyon hasonló, ha van szülő mutatók.

Mi lehet meghatározni egy rekurzív függvényt, amely megvalósítja ezt az alábbiak szerint:

  • Ha az aktuális elem a cél, vissza a bal szélső / legkisebb csomópont jogával részfa, ha létezik.
  • Recurse marad, ha a cél kisebb, mint az aktuális csomópont, és jobb, ha ez nagyobb.
  • Ha a cél az, hogy a bal és nem találtunk utódot még vissza az aktuális csomópont.

Pszeudo-kód:

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

Élő Java demo .

Válaszolt 31/12/2017 16:10
a forrás felhasználó

szavazat
1

nincs szükségünk szülő kapcsolat, vagy verem, hogy megtalálják a annak érdekében, hogy utódja O (log n) (feltételezve, hogy a kiegyensúlyozott fa). Tartson egy átmeneti változó a legutolsó értéke találkozott a inorder bejárása, amely nagyobb, mint a kulcs. ha inorder bejárása megállapítja, hogy a csomópont nem rendelkezik a jobb gyerek, akkor ez lenne a inorder utódja. más, a bal szélső leszármazottja a jobb gyermek.

Válaszolt 03/07/2018 20:07
a forrás felhasználó

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