În Succesor în binar de căutare Arbore

voturi
20

Având în vedere un nod într-un BST, cum o găsi următoarea cheie mai mare?

Întrebat 29/03/2011 la 12:25
sursa de către utilizator
În alte limbi...                            


16 răspunsuri

voturi
2

Verificați aici: Inorder Succesor într - un copac binar de căutare

În arbore binar, Inorder succesor al unui nod este următorul nod în Inorder parcurgeri de arbore binar. Inorder Succesor este nul pentru ultimul nod în Inoorder traversal. În binar de căutare Arbore, Inorder Succesor al unui nod de intrare poate fi, de asemenea, definit ca nodul cu cea mai mică cheie mai mare decât cheia nodului de intrare.

Publicat 29/03/2011 la 12:28
sursa de către utilizator

voturi
64

Modul în general, depinde de faptul dacă aveți o legătură părinte în nodurile sau nu.

Dacă păstrați legătura părinte

Apoi alegeți:

  1. Cea mai la stînga copil al copilului drept, în cazul în care nodul curent are un copil drept. În cazul în care copilul nu are dreptul nici un copil din stânga, copilul dreapta este succesorul dumneavoastră inordine.
  2. Navigați în sus nodurile strămoș părinte, și atunci când găsești un părinte al cărui copil stânga este nodul pe care ești în prezent la, părintele este succesorul inorder al nodului original.

Dacă aveți copil drept, face această abordare (caz 1 de mai sus):

inordine-când-dreapta-copil

Dacă nu aveți un copil drept, face această abordare (cazul 2 de mai sus):

inordine-când-nu-dreapta-copil

Dacă nu păstrați legătura părinte

Apoi, aveți nevoie pentru a rula o scanare completă a arborelui, păstrând evidența nodurilor, de obicei cu o stivă, astfel încât să aveți informațiile necesare pentru a face practic la fel ca și prima metodă care sa bazat pe link-ul părinte.

Publicat 29/03/2011 la 12:47
sursa de către utilizator

voturi
2

Iată o punere în aplicare, fără a fi nevoie de legături părinte sau structuri intermediare (cum ar fi o stivă). Această funcție succesor în ordine este un pic diferit de ceea ce s-ar putea să fie mai căutați, deoarece funcționează pe tasta, spre deosebire de nodul. De asemenea, se va găsi un succesor al unei taste, chiar dacă nu este prezentă în copac. Nu este prea greu pentru a schimba dacă este necesar să, cu toate acestea.

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));
    }
}
}
Publicat 27/04/2012 la 15:47
sursa de către utilizator

voturi
2

Cu binar de căutare copac, algoritmul pentru a găsi următorul cel mai mare nod al unui nod dat este de a găsi practic cel mai mic nodul de sub-arborele drept al acelui nod.

Algoritmul poate fi doar simplu:

  1. Începeți cu copilul dreapta al nodului dat (acesta nodul curent temporar face)
  2. Dacă nodul curent nu are nici un copil din stânga, este următorul cel mai mare nod.
  3. Dacă nodul curent are un copil stânga, este nodul curent face.

Se repetă 2 și 3 până când vom găsi următorul cel mai mare nod.

Publicat 02/11/2012 la 20:13
sursa de către utilizator

voturi
4

Python la Lasse a răspuns :

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
Publicat 12/01/2013 la 23:25
sursa de către utilizator

voturi
1

Soluție C ++ presupunând Nodurile au stânga, dreapta, și indicii mamă:

Aceasta ilustrează funcția Node* getNextNodeInOrder(Node)care returnează următoarea cheie a arborelui binar de căutare în ordine.

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

Care printuri:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Publicat 16/07/2013 la 19:21
sursa de către utilizator

voturi
0

Puteți citi informații suplimentare aici (Rus pulmonar)

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
Publicat 07/10/2014 la 11:25
sursa de către utilizator

voturi
0

Aceste răspunsuri toate par mult prea complicate pentru mine. Noi chiar nu au nevoie de indicii mamă sau structuri de date auxiliare, cum ar fi o stivă. Tot ce trebuie să facem este traversa copacul de la rădăcină în ordine, a stabilit un pavilion de îndată ce vom găsi nodul țintă, iar următorul nod din arborele pe care vom vizita va fi în nodul ordine succesor. Aici este o rutină rapid și murdar am scris în sus.

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);
}
Publicat 09/12/2014 la 05:29
sursa de către utilizator

voturi
1

Dacă vom efectua o în ordine traversal, atunci vom vizita subarborele stânga, apoi nodul rădăcină și în cele din urmă subarborelui drept pentru fiecare nod din arbore. Efectuarea unei pentru parcurgeri ne va da cheile unui arbore binar de căutare, în ordine crescătoare, astfel încât atunci când ne referim la preluarea în succesoare ordinea unui nod care aparține unui arbore binar de căutare ne referim la ceea ce ar fi următorul nod în secvența de la dat nodul.

Să presupunem că avem un nod R si dorim sa în ordine succesoare vom avea următoarele cazuri.

[1] Rădăcina R are un nod drept, asa ca tot ce trebuie să facem este să traverseze la cel mai nodul stânga al R-> dreapta.

[2] Rădăcina R nu are nici un nod drept, în acest caz , vom traversa din nou în sus copac urmând link - urile părinte până când nodul R este un copil stâng al părintelui său, atunci când se întâmplă acest lucru avem nodul părinte P ca și în succesoare ordine .

[3] Suntem la nodul de extremă dreapta de copac, în acest caz , nu există nici un succesor se află în ordine.

Implementarea se bazează pe următoarea definiție nod

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);
}
Publicat 10/01/2015 la 20:11
sursa de către utilizator

voturi
0

Soluție JavaScript - În cazul în care nodul dat are un nod dreapta, apoi se întoarce cel mai mic nodul din subarborelui drept - Dacă nu, atunci există 2 posibilități: - nodul dat este un copil stânga al nodului părinte. Dacă da, întoarceți nodul părinte. În caz contrar, nodul dat este un copil drept al nodului părinte. Dacă da, întoarce copilul dreapta al nodului părinte

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;
  }
}
Publicat 19/10/2015 la 03:44
sursa de către utilizator

voturi
0

Făcând acest lucru în 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);
    }
}
Publicat 22/11/2016 la 04:58
sursa de către utilizator

voturi
0

Putem împărți acest lucru în 3 cazuri:

  1. În cazul în care nodul este un părinte: În acest caz, vom afla dacă are un nod drept și traversează spre stânga copil al nodului drept. În cazul în care nodul din dreapta nu are copii, atunci nodul dreapta este succesorul său inordine. Dacă nu există nici un nod drept trebuie să se deplaseze în sus copac pentru a găsi succesorul inordine.

  2. În cazul în care nodul este un copil stânga: În acest caz, părintele este succesorul inordine.

  3. Dacă nodul (numesc x) este un copil drept (a societății-mamă imediate): Am traversa copacul până când vom găsi un nod al cărui subarbore stâng are de x.

caz extrem: Dacă nodul este nodul de colț din dreapta, nu există nici un succesor inordine.

Publicat 30/11/2016 la 10:12
sursa de către utilizator

voturi
0

Fiecare „tutorial“ pe care am verificat pe Google și toate răspunsurile în acest thread folosește următoarea logică: " Dacă nodul nu are un copil chiar atunci succesorul său în ordine va fi unul dintre strămoșii săi folosind link - ul părinte păstrează călătoresc până. veți obține nodul care este copilul stâng al părintelui său. Apoi , acest nod părinte va fi în ordine succesor. "

Acest lucru este la fel ca și de gândire „în cazul în care mama mea este mai mare decât mine, atunci eu sunt copilul din stânga “ (proprietate a unui arbore binar de căutare). Acest lucru înseamnă că puteți merge pur și simplu lanțul părinte până proprietatea de mai sus este adevărată. Care din rezultatele mele de opinie într - un cod mai elegant.

Cred că motivul pentru care toată lumea este de verificare „ sunt eu copilul lăsat “ de privirea de la sucursale în loc de valori din calea de cod care utilizeaza link - uri părinte provine de la „împrumut“ logica de algoritmul nu-link-părinte.

De asemenea , din codul inclus mai jos putem vedea nu este nevoie de structuri de date stiva după cum a sugerat alte răspunsuri.

In urma este o funcție simplă de C ++, care funcționează pentru ambele cazuri de utilizare a-(cu și fără a utiliza link-ul de la mamă).

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;
    }
}
Publicat 01/01/2017 la 13:11
sursa de către utilizator

voturi
0

C # implementare (non recursiv!) Pentru a găsi nodul „următor“ dintr-un anumit nod într-un arbore binar de căutare în cazul în care fiecare nod are o legătură către societatea mamă.

    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);
    }
Publicat 16/03/2017 la 07:15
sursa de către utilizator

voturi
0

Putem găsi succesorul în O (log n) fără a utiliza indicii părinte (pentru un arbore echilibrat).

Ideea este foarte similar cu atunci când ai indicii părinte.

Putem defini o funcție recursivă care realizează acest lucru, după cum urmează:

  • Dacă nodul curent este ținta, întoarce nodul cel mai din stânga / cea mai mică din subarborele sau dreapta, dacă există.
  • Recurse stânga dacă ținta este mai mică decât nodul curent, și la dreapta dacă este mai mare.
  • În cazul în care obiectivul este de la stânga și nu am găsit un succesor încă, a reveni nodul curent.

Pseudo cod:

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 demo - ul Java .

Publicat 31/12/2017 la 16:10
sursa de către utilizator

voturi
1

nu avem nevoie de link-ul părinte sau stivă pentru a găsi o în ordine succesoare în O (log n) (presupunând arbore echilibrat). Păstrați o variabilă temporară cu valoarea cea mai recentă întâlnită în traversal inordine, care este mai mare decât cheia. în cazul în care constată că inordine traversal nodul nu are un copil drept, atunci acest lucru ar fi succesorul inordine. altfel, cel mai din stânga descendent al copilului drept.

Publicat 03/07/2018 la 20:07
sursa de către utilizator

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