İkili Arama Ağacı sipariş Halef ise

oy
20

Bir BST bir düğüm önüne alındığında, nasıl bir sonraki daha yüksek anahtarını bulur?

Oluştur 29/03/2011 saat 12:25
kaynak kullanıcı
Diğer dillerde...                            


16 cevaplar

oy
2

Burada göz atın: Inorder Halef bir ikili arama Ağacında

İkili Ağacı olarak, bir düğümün Inorder halefi İkili Tree Inorder kastetmek sonraki düğümdür. Inorder Halef Inoorder kastetmek son düğüm için NULL olur. İkili Arama Ağacı olarak, bir giriş düğümü Inorder Halef de girdi düğümün anahtarından büyükse küçük anahtarla düğüm olarak tanımlanabilir.

Cevap 29/03/2011 saat 12:28
kaynak kullanıcı

oy
64

Genel yolu, düğümler ya da değil bir üst bağlantısı var olup olmamasına bağlıdır.

Üst bağlantı saklıyorsanız

Sonra almak:

  1. Sağ çocuğun en soldaki çocuk, geçerli düğüm bir sağ çocuğu varsa. Sağ çocuk hiçbir sol çocuğu varsa, sağ çocuk senin inorder halefi olduğunu.
  2. ebeveyn atası düğümlerini yukarı gidin ve kimin sol çocuk şu anda bulunduğunuz düğüm olan bir ebeveyne bulduğunda, ebeveyn orijinal düğümün inorder halefi olduğunu.

Doğru çocuğunuz varsa, bu yaklaşımı (yukarıdaki durum 1) yapın:

inorder-zaman-sağ çocuğa

Bir dik çocuğu yoksa, bu yaklaşımı (yukarıdaki durum 2) yapın:

inorder-zaman-no-sağ çocuğa

Üst bağlantıyı saklamak yoksa

Gerekli temelde üst bağlantıyı dayanıyordu ilk yöntem olarak aynı şeyi bilgilere sahip olmamız Sonra, genellikle bir yığın ile, düğümlerin takibi, ağacın tam tarama çalıştırmak gerekir.

Cevap 29/03/2011 saat 12:47
kaynak kullanıcı

oy
2

İşte ana bağlantıları ya da (bir yığın gibi) ara yapılar için gerek kalmadan bir uygulama bu. Bu in-order halefi işlevi düğüm aksine tuş üzerinde çalışır beri arıyor olabilir en şeye biraz farklıdır. o ağaçta mevcut değilse bile Ayrıca, bir anahtarın bir halef bulacaksınız. Eğer gerekirse çok zor değil ancak değiştirmek için.

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));
    }
}
}
Cevap 27/04/2012 saat 15:47
kaynak kullanıcı

oy
2

İkili Arama Ağacı ile, algoritma belirli bir düğümün sonraki en yüksek düğüm temelde bu düğümün sağ alt ağacın en düşük düğümü bulmaktır bulmak için.

Algoritma sadece basit olabilir:

  1. Verilen düğümün sağ çocuğu ile başlayın (geçici akım düğüm olun)
  2. Geçerli düğüm hiçbir sol çocuğu varsa, bir sonraki en yüksek düğümdür.
  3. Geçerli düğüm bir sol çocuğu varsa, geçerli düğüm olun.

bir sonraki en yüksek düğümü buluncaya kadar 2 ve 3 tekrarlayın.

Cevap 02/11/2012 saat 20:13
kaynak kullanıcı

oy
4

Lasse en Python kodu cevap :

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
Cevap 12/01/2013 saat 23:25
kaynak kullanıcı

oy
1

Düğümleri varsayarak C ++ çözüm sağ, sol, ve ebeveyn işaretçileri adres:

Bu fonksiyon göstermektedir Node* getNextNodeInOrder(Node)içinde sipariş ikili arama ağacının yanındaki anahtarı döndürür.

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

Hangi baskılar:

1 2 3 4 5 6 7 8 9 10 11

unit tests: 
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
Cevap 16/07/2013 saat 19:21
kaynak kullanıcı

oy
0

Ek bilgi okuyabilir burada (Rus akciğer)

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
Cevap 07/10/2014 saat 11:25
kaynak kullanıcı

oy
0

Bu cevaplar hepsi bana aşırı karmaşık görünüyor. Biz gerçekten ebeveyn işaretçileri veya yığını gibi herhangi bir yardımcı veri yapılarını gerek yoktur. Yapmamız gereken tek şey biz hedef düğümü bulur bulmaz bir bayrak içinde sipariş kökünden gelen ağaç ve biz sipariş halefi düğümünde olacak ziyaret ağaçta sonraki düğümü çapraz olduğunu. Benım yazdım hızlı ve kirli rutindir.

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);
}
Cevap 09/12/2014 saat 05:29
kaynak kullanıcı

oy
1

Biz sipariş kastetmek bir gerçekleştirirseniz o zaman ağaçtaki her düğüm için sol alt ağaç, daha sonra kök düğümü ve son olarak sağ alt ağacı ziyaret edin. Sipariş kastetmek bir gerçekleştirme bize artan sırada bir ikili arama ağacının anahtarlarını vermek, bu yüzden biz dan dizideki bir sonraki düğüm ne olacağını demek bir ikili arama ağacına ait bir düğüm sırası halefi alınırken bakın ne zaman olacak belirli bir düğümün.

Biz bir düğüm R var ve biz onun emri halefi biz şu durumlarda olurdu istiyorum Diyelim.

[1] kök R 'bu yüzden yapmak gerekir tamam> R- en sol düğümüne hareket için, doğru bir düğüm vardır.

[2] kök R biz sipariş halefi olduğu gibi üst düğüm P var oluştuğunda, biz düğüm R üst biriminin sol alt olana kadar üst bağlantıları takip ağacın geri çapraz bu durumda hiçbir hak düğüm vardır .

[3] Biz sipariş halefi hiçbir orada bu durumda, ağacın aşırı sağ düğüm altındadır.

uygulaması aşağıdaki düğüm tanımlanmasına dayanmaktadır

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);
}
Cevap 10/01/2015 saat 20:11
kaynak kullanıcı

oy
0

JavaScript çözümü - Verilen düğümü sağ düğüm varsa, sağ ağaca en küçük düğüm dönmek - Değilse, sonra 2 olasılık vardır: - Belirtilen düğüm üst düğümün sol çocuğudur. Eğer öyleyse, ebeveyn düğüm döner. Aksi takdirde, verilen düğüm üst düğümün sağ çocuğu. Eğer öyleyse, ebeveyn düğümün sağ çocuğu dönmek

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;
  }
}
Cevap 19/10/2015 saat 03:44
kaynak kullanıcı

oy
0

Java Bunu yapmak

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);
    }
}
Cevap 22/11/2016 saat 04:58
kaynak kullanıcı

oy
0

Biz 3 durumlarda bu bölebilirsiniz:

  1. Düğüm bir ebeveyn ise: o doğru düğüm varsa bu durumda biz bulup doğru düğümün en soldaki çocuğa geçiş. durumda sağ düğüm doğru düğüm onun inorder halefi o zaman hiçbir çocuk babasıdır. hiçbir doğru düğüm varsa biz inorder halef bulmak için ağaç yukarı taşımak gerekir.

  2. Düğüm sol alt ise: Bu durumda ebeveyn inorder halefi olduğunu.

  3. Düğüm (o x call) (onun hemen ebeveynin) sağ alt ise: biz kimin sol alt ağaç x olan bir düğüm bulana kadar ağaca çapraz.

Aşırı durum: düğüm en sağdaki köşe düğüm ise, hiçbir inorder halefi yoktur.

Cevap 30/11/2016 saat 10:12
kaynak kullanıcı

oy
0

Ben bu iplik google ve tüm cevapların kontrol Her "öğretici" aşağıdaki mantığı kullanır: " düğüm daha sonra sağ çocuğu yoksa onun içinde sipariş halefi ebeveyn bağlantı kadar seyahat tutmak kullanma atalarından biri olacak. Eğer üst biriminin sol çocuğudur düğüm. O zaman bu üst düğüm içinde sipariş halefi olacak olsun. "

Bu "düşünce aynıdır benim ebeveyn benden daha büyük ise, o zaman ben sol çocuğuyum " (ikili arama ağacının özelliği). Bu, yukarıda özellik doğrudur kadar sadece üst zincirinden yürümek anlamına gelir. Daha şık bir kod Bence sonuçlarında hangi.

Herkesin "kontrol ediyor nedenini tahmin Ben sol çocuğuyum yerine no-link-to-ebeveyn algoritmadan "borçlanma" mantık gerektirir ebeveyn bağlantıları kullanan kod yolundaki değerlerin dalları bakarak".

Ayrıca görebildiğimiz aşağıda yer koddan var yığın veri yapısı gerek diğer cevaplar önerdiği gibi.

Aşağıdaki (ve ebeveyne bağlantıyı kullanarak olmadan) hem kullanım senaryoları için çalışan basit bir C ++ işlevidir.

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;
    }
}
Cevap 01/01/2017 saat 13:11
kaynak kullanıcı

oy
0

C # uygulaması (Non özyinelemeli!) Her düğüm için üst bağlantı içeren bir ikili arama ağacında belirli bir düğümün 'next' düğümü bulmak için.

    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);
    }
Cevap 16/03/2017 saat 07:15
kaynak kullanıcı

oy
0

Biz (dengeli bir ağaç için) ana işaretçileri kullanmadan O (log n) 'de halefi bulabilirsiniz.

Fikir ebeveyn işaretçileri varken çok benzer.

Biz şöyle başarır tekrarlamalı bir fonksiyon tanımlayabilirsiniz:

  • Geçerli düğüm hedef ise varsa, onun sağ alt ağacının en soldaki / en küçük düğümünü döndürür.
  • Hedef o büyük ise akım düğümün daha küçük ve doğru ise Recurse bıraktı.
  • Hedef sola ve biz henüz bir ardıl bulamadıysanız, cari düğümü döndürür.

Sözde kod:

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

Java demo canlı .

Cevap 31/12/2017 saat 16:10
kaynak kullanıcı

oy
1

Biz ebeveyn bağlantısına ihtiyacınız yoksa (dengelenmiş ağaç varsayarak) (n günlük) O sipariş halefi bulmak yığını yok. tuşunun büyükse inorder kastetmek karşılaşılan en son değere sahip geçici bir değişken tutun. inorder geçişi düğümü sağ çocuğu yok bulursa, o zaman bu inorder halefi olacaktır. Başka sağ çocuğun en soldaki soyundan.

Cevap 03/07/2018 saat 20:07
kaynak kullanıcı

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