Za účelem nástupce strom binárního vyhledávání

hlasů
20

Vzhledem k tomu, uzel v BST, jak se dá najít nejbližší vyšší klíč?

Položena 29/03/2011 v 12:25
zdroj uživatelem
V jiných jazycích...                            


16 odpovědí

hlasů
2

Podívejte se zde: nezbytného nástupce binární vyhledávací strom

V binární strom, Nezbytného nástupce uzlu je další uzel v nezbytného průchod binárního stromu. Nezbytného nástupce je NULL pro poslední uzel v Inoorder průchod. V binární vyhledávací strom, Nezbytného nástupce ze vstupního uzlu může být také definována jako uzel s nejmenším klíčem je větší než klíč vstupního uzlu.

Odpovězeno 29/03/2011 v 12:28
zdroj uživatelem

hlasů
64

Obecný způsob závisí na tom, zda máte nadřazený odkaz ve svých uzlech, či nikoli.

Pokud ukládáte nadřazený odkaz

Pak si vyberete:

  1. Nejvíce vlevo dítě správným dítěte, je-li aktuální uzel má pravý dítě. V případě, že právo dítěte nemá levou dítěte, právo dítěte je váš nezbytného nástupce.
  2. Navigate up předchůdce uzly mateřské, a když zjistíte, rodič, jehož dítě vlevo je uzel, že jste v současné době, která je mateřskou je nezbytného nástupcem původní uzlu.

Pokud máte správného dítě, proveďte tento postup (případ 1 výše):

nezbytného-kdy-pravé dítě

Pokud nechcete mít právo dítě, proveďte tento postup (případ 2 výše):

nezbytného-kdy-no-pravé dítě

Pokud nechcete ukládat nadřazený odkaz

Pak budete muset spustit úplnou kontrolu stromu, sledování uzlů, obvykle s komínem, takže máte informace nezbytné pro v podstatě to samé jako první metoda, která vycházela z mateřské odkaz.

Odpovězeno 29/03/2011 v 12:47
zdroj uživatelem

hlasů
2

Zde je implementace bez nutnosti mateřských vazeb či zprostředkovatelských struktur (jako stoh). Tato funkce nástupce in-cílem je trochu odlišný od toho, co nejvíce by mohlo být hledáme, protože pracuje na tlačítku na rozdíl od uzlu. Také bude hledat nástupce klíče, i když není přítomen ve stromu. Není příliš těžké změnit, pokud jste potřebovali, nicméně.

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));
    }
}
}
Odpovězeno 27/04/2012 v 15:47
zdroj uživatelem

hlasů
2

S binární vyhledávací strom, algoritmus najít další nejvyšší uzel daného uzlu je v podstatě najít nodu pravého podstromu daného uzlu.

Algoritmus může být jednoduše:

  1. Začněte s pravým dítětem daného uzlu (umožňují dočasné aktuální uzel)
  2. Pokud je aktuální uzel nemá levé dítě, to je další nejvyšší uzel.
  3. Pokud je aktuální uzel má levé dítě, aby bylo aktuální uzel.

Opakujte 2 a 3, dokud nenajdeme další nejvyšší uzel.

Odpovězeno 02/11/2012 v 20:13
zdroj uživatelem

hlasů
4

Python kód Lasse je odpověď :

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
Odpovězeno 12/01/2013 v 23:25
zdroj uživatelem

hlasů
1

C ++ řešení za předpokladu, že uzly mají vlevo, vpravo, a mateřské ukazatele:

To ukazuje funkci Node* getNextNodeInOrder(Node), která vrací další klíč od binárního vyhledávacího stromu na zakázku.

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

Která tiskne:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Odpovězeno 16/07/2013 v 19:21
zdroj uživatelem

hlasů
0

Si můžete přečíst další informace zde (Rus plic)

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
Odpovězeno 07/10/2014 v 11:25
zdroj uživatelem

hlasů
0

Tyto odpovědi jsou všechny se zdají příliš složité pro mě. Opravdu nepotřebujeme rodičovských rad nebo jakékoliv pomocné datové struktury, jako zásobníku. Vše, co musíme udělat, je procházet strom z kořene in-pořadí, nastavit příznak, jakmile najdeme cílový uzel a další uzel ve stromu, které navštívíme bude v pořadí následníků uzlu. Zde je rychlý a špinavý rutinní jsem sepsal.

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);
}
Odpovězeno 09/12/2014 v 05:29
zdroj uživatelem

hlasů
1

Budeme-li provést v pořadí průchod pak navštívíme levý podstrom, pak kořen a nakonec pravého podstromu pro každý uzel ve stromu. Provedení na objednávku průchod nám dá klíče od binárního vyhledávacího stromu ve vzestupném pořadí, takže když jsme se vztahují k načítání v pořadí nástupce uzlu, který patří do binárního vyhledávacího stromu máme na mysli to, co bude příští uzel v pořadí z daný uzel.

Řekněme máme uzlu R a chceme jeho v pořadí nástupce bychom měli tyto případy.

[1] Kořen R má pravý uzel, takže vše, co je třeba udělat, je přejít na nejvíce vlevo uzlu R-> doprava.

[2] Kořen R nemá právo uzlu, v tomto případě se přetínat zpět stromu po nadřazené odkazy dokud uzel R je levý dítě svého rodiče, když k tomu dojde, máme na rodičovský uzel P jako v pořadí nástupce ,

[3] Jsme na zcela vpravo uzlu stromu, v tomto případě není v pořádku nástupce.

Implementace je založeno na následující definici uzlu

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);
}
Odpovězeno 10/01/2015 v 20:11
zdroj uživatelem

hlasů
0

Řešení JavaScript - V případě, že daný uzel má pravý uzel, pak se vrátí nejmenší uzel v pravém podstromu - Pokud tomu tak není, pak jsou 2 možnosti: - Daný uzel je vlevo dítě nadřazeného uzlu. Pokud ano, vrátí nadřazený uzel. V opačném případě je daný uzel je právo dítě nadřazeného uzlu. Pokud ano, vrátí správné dítě nadřazeného uzlu

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;
  }
}
Odpovězeno 19/10/2015 v 03:44
zdroj uživatelem

hlasů
0

Přitom v Javě

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);
    }
}
Odpovězeno 22/11/2016 v 04:58
zdroj uživatelem

hlasů
0

To můžeme rozdělit do 3 případy:

  1. V případě, že uzel je rodič: V tomto případě jsme se zjistit, zda má správnou uzel a přejít na zcela vlevo dítě pravého uzlu. V případě, že pravý uzel nemá děti, pak vpravo uzel je jeho nezbytného nástupce. Pokud není k dispozici správná uzel musíme přesunout do stromu najít nezbytného nástupce.

  2. V případě, že uzel je vlevo dítě: V tomto případě je rodič je nezbytného nástupce.

  3. V případě, že uzel (nazvat x) je právo dítě (jeho bezprostředním mateřským podnikem): jsme procházet na strom, dokud nenajdeme uzel, jehož levý podstrom má x.

Extrémním případem: Pokud uzel je nejvíce vpravo rohový uzel není nezbytného nástupce.

Odpovězeno 30/11/2016 v 10:12
zdroj uživatelem

hlasů
0

Každý „tutorial“, že jsem se díval na google a všechny odpovědi v tomto vlákně používá následující logiku: " Pokud uzel nemá správné dítě pak jeho in-pořadí nástupcem se stane jedním z jeho předků Použití rodič odkaz držet na cestách až do. dostanete uzlu, který je na levé dítě jeho rodiče. Pak se tento rodič uzel bude nástupcem in-pořadí. "

To je stejné jako myšlení „pokud má rodič je větší než já, pak já jsem tou levou dítě “ (vlastnost binárního vyhledávacího stromu). To znamená, že můžete jednoduše jít do nadřazené řetěz až do výše vlastnost je pravda. Který ve svých výsledcích mínění v elegantnější kódu.

Myslím, že důvod, proč je každý běžný „ já jsem opustil dítě “ při pohledu na pobočkách namísto hodnot v cestě kódu, který využívá odkazy rodiče pochází z „výpůjčky“ logiky z algoritmu no-link-to-rodič.

Také z přiloženého kódu níže můžeme vidět není žádná potřeba pro datové struktury zásobníku , jak navrhuje další odpovědi.

Následující jednoduchý C funkce ++, která funguje pro užitných případech (s a bez použití odkaz na rodiče).

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;
    }
}
Odpovězeno 01/01/2017 v 13:11
zdroj uživatelem

hlasů
0

C implementace # (Non rekurzivní!) Najít ‚NEXT‘ uzel daného uzlu v binárním vyhledávacím stromu, kde každý uzel má odkaz na své mateřské společnosti.

    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);
    }
Odpovězeno 16/03/2017 v 07:15
zdroj uživatelem

hlasů
0

Můžeme najít nástupce v O (log n) bez použití nadřazených ukazatele (pro vyvážený strom).

Myšlenka je velmi podobný tomu, když máte nadřazené ukazatele.

Můžeme definovat rekurzivní funkci, která dosahuje to následujícím způsobem:

  • Pokud je aktuální uzel je cíl, vrátit nejvíce vlevo / nejmenší uzel pravém podstromu, pokud existuje.
  • Recurse opustil v případě, že cíl je menší než aktuální node, a v pořádku, pokud je to větší.
  • V případě, že cíl je na levé straně a my jsme nenašli nástupce přesto, vrátí aktuální uzel.

Pseudo 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

Žít Java demo .

Odpovězeno 31/12/2017 v 16:10
zdroj uživatelem

hlasů
1

my dont potřeba mateřský odkaz nebo stoh najít v pořadí nástupce v O (log n) (za předpokladu, že vyvážený strom). Zachovat dočasné proměnné s poslední hodnotou vyskytly při nezbytného průchod, který je větší, než je klíč. v případě nezbytného traversal zjistí, že uzel nemá správné dítě, pak by to bylo nezbytného nástupce. jinde, nejvíce vlevo potomek pravého dítěte.

Odpovězeno 03/07/2018 v 20:07
zdroj uživatelem

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