I Bestill etterfølger i binært søketre

stemmer
22

Gitt en node i et BST, hvordan finner man det neste høyere nøkkelen?

Publisert på 29/03/2011 klokken 11:25
kilden bruker
På andre språk...                            


16 svar

stemmer
2

Sjekk ut her: inorder etterfølger i et binært søketre

I Binary forfedre Inorder etterfølger av en node er neste node i Inorder traversering av Binary treet. Inorder etterfølger er NULL for siste node i Inoorder traversering. I binært søketre, kan Inorder etterfølger en inngangsnode også defineres som noden med den minste nøkkelen større enn nøkkelen til inngangsnode.

Svarte 29/03/2011 kl. 11:28
kilden bruker

stemmer
65

Den generelle måten avhenger av om du har en forelder link i dine noder eller ikke.

Hvis du lagrer den overordnede koblingen

Deretter velger du:

  1. Lengst til venstre barn av retten barnet, hvis din nåværende node har rett barn. Hvis retten barnet har ingen venstre barn, er det rette barnet inorder etterfølger.
  2. Naviger opp foreldre stamfar noder, og når du finner en forelder som venstre barn er noden du er for tiden på, er den overordnede inorder etterfølger til den opprinnelige noden.

Hvis du har riktig barn, gjør denne tilnærmingen (case 1 ovenfor):

inorder-når-høyre-barn

Hvis du ikke har rett til barn, gjør denne tilnærmingen (tilfelle 2 ovenfor):

inorder-da-no-høyre-barn

Hvis du ikke lagrer den overordnede koblingen

Deretter må du kjøre en fullstendig skanning av treet, holde styr på nodene, vanligvis med en stabel, slik at du har nødvendig informasjon for å i utgangspunktet gjøre det samme som den første metoden som støttet seg på den overordnede link.

Svarte 29/03/2011 kl. 11:47
kilden bruker

stemmer
2

Her er en implementering uten behov for overordnede linker eller mellomliggende strukturer (for eksempel en stabel). Dette i-order etterfølger funksjonen er litt annerledes enn hva de fleste kan være ute etter, siden den opererer på nøkkelen i motsetning til noden. Dessuten vil det finne en etterfølger av en nøkkel, selv om det ikke er til stede i treet. Ikke så vanskelig å endre hvis du trengte å, imidlertid.

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));
    }
}
}
Svarte 27/04/2012 kl. 14:47
kilden bruker

stemmer
2

Med binært søketre, til algoritmen finne den nest høyeste node til en gitt node er i utgangspunktet å finne den laveste noden i høyre sub-tre av den noden.

Algoritmen kan bare være enkelt:

  1. Begynn med høyre barn av gitt node (gjøre den midlertidige gjeldende node)
  2. Hvis gjeldende node har ingen venstre barn, er det nest høyeste node.
  3. Hvis gjeldende node har en venstre barn, gjør det gjeldende node.

Gjenta 2 og 3 til vi finner nest høyeste node.

Svarte 02/11/2012 kl. 19:13
kilden bruker

stemmer
4

Python koden til Lasses svaret :

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
Svarte 12/01/2013 kl. 22:25
kilden bruker

stemmer
1

C ++ løsning forutsatt noder har venstre, høyre, og foreldre tips:

Dette illustrerer funksjonen Node* getNextNodeInOrder(Node)som returnerer neste nøkkelen til binært søketre i bestilling.

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

Som utskrifter:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Svarte 16/07/2013 kl. 18:21
kilden bruker

stemmer
0

Du kan lese mer info her (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
Svarte 07/10/2014 kl. 10:25
kilden bruker

stemmer
0

Disse svarene alle synes altfor komplisert for meg. Vi trenger ikke foreldrepekere eller andre hjelpedatastrukturer som en stabel. Alt vi trenger å gjøre er å traversere treet fra roten i bestilling, sette et flagg så snart vi finne målet node, og neste node i treet som vi besøker vil være i orden etterfølger node. Her er en rask og skitne rutine jeg skrev opp.

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);
}
Svarte 09/12/2014 kl. 05:29
kilden bruker

stemmer
1

Hvis vi utfører en for traversering da vi besøker venstre treet, så root node og til slutt høyre subtre for hver node i treet. Utføre en for traversering vil gi oss nøklene til et binært søketre i stigende rekkefølge, så når vi refererer til å hente den for etterfølgeren av en node som tilhører et binært søketre vi mener det vil være det neste node i sekvensen fra den gitte node.

La oss si vi har en node R og vi ønsker det for etterfølgeren ville vi ha følgende tilfeller.

[1] Roten R har en rett node, slik at alt vi trenger å gjøre er å traversere å lengst til venstre noden i R-> høyre.

[2] Den grunnlegg R har ingen rett node, i dette tilfelle vi traversere tilbake opp treet følgende mor- koblingene til noden R er et venstre barn av foreldre, når dette skjer vi har foreldrenoden P som i rekkefølge etterfølger .

[3] Vi er på det ekstreme høyre node i treet, i dette tilfellet er det ingen i orden etterfølger.

Gjennomføringen er basert på følgende noden definisjonen

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);
}
Svarte 10/01/2015 kl. 20:11
kilden bruker

stemmer
0

Javascript løsning - Hvis gitt node har rett node, deretter returnere den minste node i riktig treet - Hvis ikke, så er det 2 muligheter: - Den oppgitte noden er en venstre barn av foreldrenoden. I så fall tilbake foreldrenoden. Ellers er gitt node rett barn av foreldrenoden. Hvis ja, gå tilbake til høyre barn av foreldrenoden

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;
  }
}
Svarte 19/10/2015 kl. 03:44
kilden bruker

stemmer
0

Å gjøre dette i 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);
    }
}
Svarte 22/11/2016 kl. 04:58
kilden bruker

stemmer
0

Vi kan dele dette i 3 tilfeller:

  1. Hvis noden er en forelder: I dette tilfellet finner vi hvis det har en riktig node og krysse til den nest siste barnet av retten node. Ved riktig node har ingen barn så høyre node er dens inorder etterfølger. Hvis det ikke er riktig node må vi flytte opp treet for å finne den inorder etterfølger.

  2. Hvis noden er en venstre barn: I dette tilfellet foreldrene er inorder etterfølger.

  3. Hvis noden (kaller det x) er en rettighet barn (av dens umiddelbare overordnede): Vi krysser opp treet til vi finner en node som venstre subtre har x.

Ekstremt tilfelle: Dersom noden er lengst til høyre hjørne node, er det ingen inorder etterfølger.

Svarte 30/11/2016 kl. 10:12
kilden bruker

stemmer
0

Hver "tutorial" som jeg sjekket på google og alle svarene i denne tråden bruker følgende logikk: " Hvis noden ikke har rett til barnet deretter sin i-order etterfølger vil være en av sine forfedre ved hjelp av foreldrene linken holde reiser frem til. du får node som er venstre barn av sin overordnede. Da er dette overordnede noden vil være i for etterfølger. "

Dette er det samme som å tenke " hvis foreldrene mine er større enn meg, så jeg er venstre barn " (eies av et binært søketre). Dette betyr at du kan bare gå opp den overordnede kjeden til ovennevnte eiendom er sant. Som etter min mening gir en mer elegant kode.

Jeg tror grunnen til at alle ser " er jeg forlot barnet " ved å se på grener i stedet for verdier i kodebanen som utnytter foreldre linker kommer fra "låne" logikk fra nei-link-to-foreldre-algoritmen.

Også fra den medfølgende koden under vi kan se er det ikke behov for stack datastruktur som foreslått av andre svar.

Følgende er en enkel C ++ funksjon som fungerer for begge bruks-trekk (med og uten anvendelse av kobling til moder).

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;
    }
}
Svarte 01/01/2017 kl. 13:11
kilden bruker

stemmer
0

C # implementering (Non rekursiv!) For å finne den 'neste' node til en gitt node i et binært søketre der hver node har en link til sin overordnede.

    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);
    }
Svarte 16/03/2017 kl. 07:15
kilden bruker

stemmer
0

Vi kan finne følgeren i O (log n) uten bruk av foreldre pekere (for en balansert tre).

Ideen er veldig lik når du har foreldrepekere.

Vi kan definere en rekursiv funksjon som oppnår dette på følgende måte:

  • Hvis den aktuelle noden er målet, returnere lengst til venstre / minste node av sin rett treet, hvis den finnes.
  • Recurse venstre hvis målet er mindre enn den nåværende node, og høyre om det er større.
  • Hvis målet er til venstre, og vi har ikke funnet en etterfølger ennå, returnerer gjeldende node.

Pseudo-kode:

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

Leve Java demo .

Svarte 31/12/2017 kl. 16:10
kilden bruker

stemmer
1

vi trenger moder kobling eller stabel for å finne den for etterfølger in O (log n) (forutsatt balansert tre). Hold en midlertidig variabel med den nyeste verdien oppstått i inorder traversering som er større enn nøkkelen. hvis inorder traversering finner at noden ikke har rett barn, da dette ville være den inorder etterfølger. annet, lengst til venstre kommer av høyre barn.

Svarte 03/07/2018 kl. 20:07
kilden bruker

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