एक BST में एक नोड को देखते हुए, कैसे एक अगले उच्च कुंजी मिल रहा है?
द्विआधारी खोज वृक्ष में आदेश उत्तराधिकारी में
यहाँ की जाँच करें एक द्विआधारी खोज वृक्ष में inorder उत्तराधिकारी
बाइनरी ट्री में, एक नोड के लिए inorder उत्तराधिकारी बाइनरी ट्री के लिए inorder ट्रावर्सल में अगले नोड है। Inorder उत्तराधिकारी Inoorder ट्रेवर्सल में पिछले नोड के लिए शून्य है। द्विआधारी खोज वृक्ष में, एक इनपुट नोड के लिए inorder उत्तराधिकारी भी इनपुट नोड के प्रमुख से अधिक छोटी से छोटी कुंजी के साथ नोड के रूप में परिभाषित किया जा सकता है।
सामान्य तरीके से कि क्या आप अपने नोड्स या नहीं में एक माता पिता लिंक पर निर्भर करता है।
आप माता-पिता लिंक संग्रहीत करते हैं
तो फिर तुम लेने:
- सही बच्चे के सबसे बाईं ओर बच्चे, अपने वर्तमान नोड एक सही बच्चा है यदि। सही बच्चे की कोई बाईं बच्चा है, तो सही बच्चे अपने inorder उत्तराधिकारी है।
- माता-पिता पूर्वज नोड्स ऊपर नेविगेट, और जब आप एक माता पिता जिसका बाईं चाइल्ड नोड आप वर्तमान में कर रहे है, माता पिता अपने मूल नोड के लिए inorder उत्तराधिकारी है।
आप सही बच्चा है, इस दृष्टिकोण (उपरोक्त मामले 1) कार्य करें:

यदि आप एक सही बच्चे नहीं है, तो, इस दृष्टिकोण (उपरोक्त मामले 2) कार्य करें:

आप माता-पिता लिंक की दुकान नहीं है, तो
तो फिर तुम पेड़ की एक पूरी स्कैन चलाने की जरूरत है, आम तौर पर एक ढेर के साथ, नोड्स का ट्रैक रखने, ताकि आप मूल रूप से पहली विधि है कि माता-पिता लिंक पर भरोसा के रूप में भी ऐसा ही करने के लिए आवश्यक जानकारी नहीं है।
यहाँ माता-पिता लिंक या मध्यवर्ती संरचनाएं (एक ढेर की तरह) की आवश्यकता के बिना एक कार्यान्वयन है। यह इन-आदेश उत्तराधिकारी समारोह एक सा जो सबसे अधिक के बाद से यह कुंजी के रूप में नोड के लिए विरोध पर चल रही है की तलाश में हो सकता है के लिए अलग है। इसके अलावा, यह एक प्रमुख के उत्तराधिकारी भले ही वह पेड़ में मौजूद नहीं है मिल जाएगा। यदि आप करने के लिए आवश्यक परिवर्तन करने के लिए नहीं बहुत कठिन है, लेकिन।
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));
}
}
}
द्विआधारी खोज वृक्ष के साथ, एल्गोरिथ्म एक दिया नोड के अगले सर्वोच्च नोड मूल रूप से उस नोड के अधिकार उप पेड़ के निम्नतम नोड रही है खोजने के लिए।
एल्गोरिथ्म बस हो सकता है:
- दिए गए नोड के सही बच्चे के साथ प्रारंभ करें (यह अस्थायी वर्तमान नोड बनाने)
- वर्तमान नोड कोई बाईं बच्चे है, यह अगले सर्वोच्च नोड है।
- वर्तमान नोड एक छोड़ दिया बच्चे को है, यह वर्तमान नोड बनाते हैं।
दोहराएँ 2 और 3 जब तक हम अगले सर्वोच्च नोड पाते हैं।
लासे के लिए अजगर कोड जवाब :
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
सी ++ समाधान नोड्स के बावजूद छोड़ दिया है ठीक है, और माता पिता के संकेत:
इस समारोह को दिखाता है Node* getNextNodeInOrder(Node), जिसमें से आदेश द्विआधारी खोज वृक्ष की अगली कुंजी देता है।
#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;
}
कौन सा प्रिंट:
1 2 3 4 5 6 7 8 9 10 11
unit tests:
passed01
passed02
passed03
passed04
passed05
passed06
passed07
passed08
passed09
आप अतिरिक्त जानकारी पढ़ सकते हैं यहाँ (रस फेफड़ों)
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
इन सवालों के जवाब सब बहुत ज्यादा मेरे लिए जटिल लगते हैं। हम वास्तव में माता पिता के संकेत दिए गए या एक ढेर की तरह किसी भी सहायक डेटा संरचनाओं की जरूरत नहीं है। हम सभी के लिए आपको बस-आदेश जड़, के रूप में जल्द ही एक ध्वज सेट के रूप में हम लक्ष्य नोड को खोजने से पेड़, और पेड़ है कि हम पर जाएँ आदेश उत्तराधिकारी नोड में हो जाएगा में अगले नोड पार है। यहाँ एक त्वरित और गंदी दिनचर्या मैं लिखा है।
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);
}
अगर हम आदेश ट्रावर्सल में एक प्रदर्शन तो हम पेड़ में प्रत्येक नोड के लिए छोड़ दिया सबट्री, तो रूट नोड और अंत में सही सबट्री जाएँ। आदेश ट्रावर्सल में एक प्रदर्शन हमें आरोही क्रम में एक द्विआधारी खोज वृक्ष की कुंजियां दूंगा, इसलिए जब हम एक नोड एक द्विआधारी खोज वृक्ष हमारा मतलब क्या से अनुक्रम में अगले नोड होगा से संबंधित के आदेश उत्तराधिकारी में पुन: प्राप्त करने का उल्लेख दिए गए नोड।
कहते हैं कि चलो हम एक नोड आर है और हम चाहते हैं अपने आदेश उत्तराधिकारी में हम निम्नलिखित मामलों के लिए होगा।
[1] जड़ आर एक सही नोड है, इसलिए हम सभी सब करने की ज़रूरत R- के बाएँ सबसे नोड के लिए पार करने के लिए है> सही।
[2] जड़ आर का कोई अधिकार नहीं नोड, इस मामले में हम माता-पिता लिंक का अनुसरण तक नोड आर अपनी मूल के एक छोड़ दिया बच्चा है पेड़ पर वापस पार है, ऐसा नहीं होने पर हम आदेश उत्तराधिकारी के रूप में माता पिता के नोड पी है ।
[3] हम पेड़ के चरम सही नोड पर कर रहे हैं, ताकि उत्तराधिकारी में नहीं है इस मामले में वहाँ।
कार्यान्वयन निम्नलिखित नोड परिभाषा पर आधारित है
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);
}
जावास्क्रिप्ट समाधान - दिए गए नोड एक सही नोड है, तो सही सबट्री में सबसे छोटी नोड वापसी - यदि नहीं, तो वहाँ 2 संभावनाएं हैं: - दिये गये नोड माता पिता नोड के एक छोड़ दिया बच्चा है। यदि हां, तो माता-पिता नोड लौट आते हैं। अन्यथा, दिए गए नोड माता पिता नोड का एक सही बच्चा है। यदि हां, तो माता-पिता नोड के सही बच्चे वापसी
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;
}
}
जावा में ऐसा करने से
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);
}
}
हम 3 मामलों में इस विभाजित कर सकते हैं:
नोड एक माता पिता है: इस मामले में हम पाते हैं कि यह एक सही नोड है और सही नोड के सबसे बाईं ओर के बच्चे को बढ़ावा देते हैं। मामले में सही नोड सही नोड अपने inorder उत्तराधिकारी है तो कोई संतान नहीं है। अगर कोई सही नोड है हम inorder उत्तराधिकारी खोजने के लिए पेड़ पर बढ़ने की जरूरत है।
नोड एक छोड़ दिया बच्चा है: इस मामले में माता-पिता inorder उत्तराधिकारी है।
नोड (फोन यह x) (इसके तत्काल माता पिता की) एक सही बच्चा है: हम जब तक हम एक नोड जिसका बाईं सबट्री एक्स है खोजने के पेड़ पर बढ़ावा देते हैं।
चरम मामला: नोड सबसे दायीं ओर कोने नोड है, तो कोई inorder उत्तराधिकारी है।
हर "ट्यूटोरियल" है कि मैं इस सूत्र में गूगल और सभी उत्तर पर जाँच की निम्न तर्क का उपयोग करता: " नोड एक सही बच्चे तो नहीं है, तो उसके इन-आदेश उत्तराधिकारी अपने पूर्वजों में से एक होगी माता पिता लिंक तक यात्रा रखने का उपयोग करना। आप नोड जो अपनी मूल के बाईं बच्चे। फिर इस माता पिता नोड में क्रम के उत्तराधिकारी हो जाएगा मिलता है। "
यह सोच "के रूप में एक ही है कि मेरे माता-पिता मुझे तुलना में बड़ा है, तो मैं छोड़ दिया बच्चा हूँ " (एक द्विआधारी खोज वृक्ष की संपत्ति)। इसका मतलब यह है कि आप केवल माता-पिता श्रृंखला चल सकता है जब तक ऊपर संपत्ति सच है। एक और अधिक सुरुचिपूर्ण कोड में मेरी राय परिणामों में कौन सा।
मैं कारण है कि हर किसी को जाँच कर रहा है लगता है कि " मैं चला गया बच्चा हूँ शाखाओं कोड रास्ता है कि माता-पिता लिंक का इस्तेमाल नहीं-लिंक करने वाली माता पिता एल्गोरिथ्म से" उधार "तर्क से आता है में मान के स्थान को देखकर"।
भी शामिल कोड के नीचे हम देख सकते हैं वहाँ से ढेर डेटा संरचना के लिए कोई जरूरत के रूप में अन्य उत्तर ने सुझाव दिया।
के बाद एक साधारण सी ++ समारोह है कि (के साथ और माता पिता के लिए लिंक का उपयोग किए बिना) दोनों का उपयोग-मामलों के लिए काम करता है।
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;
}
}
सी # कार्यान्वयन (गैर पुनरावर्ती!) एक द्विआधारी खोज वृक्ष जहां प्रत्येक नोड इसके जनक लिए एक लिंक है में दिए गए नोड के 'अगले' नोड खोजने के लिए।
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);
}
हम (एक संतुलित पेड़ के लिए) माता-पिता संकेत का उपयोग किए बिना ओ (लॉग एन) में उत्तराधिकारी पा सकते हैं।
विचार बहुत आप माता-पिता संकेत है जब के समान है।
हम एक पुनरावर्ती समारोह है कि इस को प्राप्त होता है इस प्रकार परिभाषित कर सकते हैं:
- वर्तमान नोड लक्ष्य है, तो इसकी सही सबट्री का सबसे बाईं ओर / छोटी से छोटी नोड लौटने के लिए, यदि वह मौजूद है।
- Recurse छोड़ दिया है, तो लक्ष्य वर्तमान नोड की तुलना में छोटे, और सही अगर यह अधिक से अधिक है।
- लक्ष्य बाईं ओर है और हम अभी तक एक उत्तराधिकारी नहीं मिला है, तो वर्तमान नोड लौट आते हैं।
छद्म कोड:
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
हम माता पिता के लिंक की जरूरत है या हे में आदेश उत्तराधिकारी खोजने के लिए ढेर (लॉग एन) (संतुलित पेड़ कल्पना करते हुए) नहीं है। सबसे हाल ही में inorder ट्रावर्सल कुंजी से भी बड़ा है कि में आई मूल्य के साथ एक अस्थायी चर रखें। inorder ट्रावर्सल पता लगता है कि नोड एक सही बच्चे नहीं है, तो यह inorder उत्तराधिकारी होगा। बाकी, सही बच्चे की वाम-पंथी वंशज।













