एक BST में बदली नोड्स का पता लगाएं

वोट
6

मैं एक प्रोग्राम है जो पता लगाने और BST में दो नोड्स कि बदली की है मुद्रित कर सकते हैं लिखने के लिए कोशिश कर रहा हूँ।

एक तीन स्तर ट्री में, मैं समाधान इस दृष्टिकोण का उपयोग करने के लिए पास पहुंच गया।

If (!AllSubTreeAreValid())
{
//Nodes swapped on same side of main root node
}
else
{
  int max = getMax(root->left);
  int min = getMin(root->right);
  if(max > root->data || min < root->data )
  {
     //Nodes swapped on different sides of main root node
     //Print max and min values

  }
else 
{
 //No node swappped
}
}

//Helper functions
int GetMaxEle(TreeNode* tree)
{
    while(tree->right!=NULL)
    {
        tree=tree->right;
    }
    return tree->info;
}

int GetMinEle(TreeNode* tree)
{
    while(tree->left!=NULL)
    {
        tree=tree->left;
    }
    return tree->info;
}

लेकिन इसके बाद के संस्करण दृष्टिकोण में विफल रहा है जब मैं चार स्तर के पेड़ के साथ परीक्षण करने के लिए कोशिश की।

             20

      15            30

   10    17       25     33

9  16  12  18  22  26  31  34

रूट नोड 15 के दाहिने सबट्री में होने के नाते, 12 अभी भी अधिक से अधिक (उल्लंघन) है।

रूट नोड 15 के बाएं सबट्री में होने के नाते, 16 अभी भी अधिक से अधिक (उल्लंघन) है।

तो, 16, 12 से ऊपर BST में बदली तत्व हैं। कैसे मैं उन्हें कार्यक्रम के माध्यम से मिल सकती है?

31/08/2011 को 17:30
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


3 जवाब

वोट
0

मैं अपने getMin एट getMax परिकल्पना कि पेड़ एक BST है witht काम करता है, तो लगता है कि

T getMax(tree) {
  return tree -> right == null 
    ? tree -> value 
    : getMax(tree -> right);
}

(या एक पाश के साथ बराबर कोड)। यदि हां, तो आपके कोड पेड़ में सबसे कम तीन मानों का पता लगाता। यहां तक ​​कि अगर getMax और getMin वास्तविक अधिकतम / मिनट पाने के लिए पूरा पेड़ चल, आप अभी भी सिर्फ दो तुलना पर अपने परीक्षण के आधार पर होगा। आप देखना होगा कि आपकी पेड़ BST संपत्ति को पूरा करना चाहते हैं, यह स्पष्ट है कि आप सभी मूल्यों की जांच करना है। इसके लिए पर्याप्त अपने माता पिता के साथ प्रत्येक नोड तुलना करने के लिए।

void CheckIsBst(Tree *tree) {
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
    }
    CheckIsBst(tree -> left);   
  }
  // same with -> right, reversing < to > in the test
}

संपादित करें : कि गलत था, टिप्पणी देखें। मेरा मानना है कि यह एक ठीक है।

void checkIsBst(Tree *Tree, Tree *lowerBound, Tree *upperBound) {
  if(lowerBound!= null && lowerBound -> value > tree -> Value) {
    //violation
  }
  // same for upper bound, check with <
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
     }
     CheckIsBst(tree -> left, lowerBound, tree);   
  }
  // same for right, reversing comparison 
  // setting lowerBound to tree instead of upperBound
}

अशक्त सीमा के साथ जड़ से कॉलिंग

31/08/2011 को 18:03
का स्रोत उपयोगकर्ता

वोट
8

एक तरह से इस समस्या के बारे में सोचने के लिए तथ्य यह है कि पेड़ की एक inorder की पैदल दूरी पर क्रमबद्ध क्रम में सभी तत्त्व का उत्पादन करेगा उपयोग करने के लिए है। आप इस चलने के दौरान क्रमबद्ध आदेश से विचलन का पता लगा सकते हैं, तो आप दो तत्वों है कि गलत जगह में हैं का पता लगाने की कोशिश कर सकते हैं।

चलो कैसे पहले एक सरल क्रमबद्ध सरणी के लिए यह करने के लिए देखते हैं, तो हमारे एल्गोरिथ्म का उपयोग करेगा कुछ है कि पेड़ पर काम करता है बनाने के लिए। Intuitively, अगर हम एक क्रमबद्ध सरणी के साथ शुरू और फिर दो (गैर बराबर!) तत्वों स्वैप, हम सरणी जगह से बाहर किया जा रहा है में तत्वों में से कुछ संख्या के साथ खत्म हो जाएगा। उदाहरण के लिए, सरणी दिया

1 2 3 4 5

अगर हम स्वैप 2 और 4, हम इस सरणी के साथ अंत:

1 4 3 2 5

हम कैसे पता लगाता है कि 2 और 4 यहाँ बदली कर रहे थे? ठीक है, के बाद से 4 दो तत्वों की अधिक से अधिक है और नीचे की अदला-बदली की गई थी, यह उसके चारों ओर तत्वों की दोनों से अधिक होना चाहिए। इसी तरह, क्योंकि 2 अप बदली गया था, यह उसके चारों ओर तत्वों की दोनों से छोटा होना चाहिए। इस से, हम यह निष्कर्ष निकाल सकता है कि 2 और 4 बदली कर रहे थे।

बहरहाल, यह हमेशा सही ढंग से काम नहीं करता है। उदाहरण के लिए, मान लीजिए कि हम स्वैप 1 और 4:

4 2 3 1 5

इधर, दोनों 2 और 1 उनके पड़ोसी तत्वों की तुलना में छोटे हैं, और दोनों 4 और 3 उनकी से बड़े होते हैं। इस से हम कह सकते हैं कि इन चार किसी भी तरह के दो बदली रहे थे, लेकिन यह स्पष्ट नहीं है कि कौन सा हम आपस में बदल जाना चाहिए। हालांकि, अगर हम सबसे बड़े और इन मूल्यों (1 और 4, क्रमशः) की सबसे छोटी ले, हम जोड़ी है कि बदली था हो रही अंत।

आम तौर पर, तत्वों है कि अनुक्रम में बदली रहे थे खोजने के लिए, आप ढूंढना चाहते हैं

  • सरणी में सबसे बड़ा स्थानीय अधिकतम।
  • सरणी में सबसे छोटी स्थानीय न्यूनतम।

इन दोनों तत्वों जगह से बाहर हैं और बदली किया जाना चाहिए।

अब, चलो कैसे पेड़ों को यह लागू करने के लिए के बारे में सोचते हैं। पेड़ के आदेश से बाहर दो तत्वों के साथ हल कर अनुक्रम का उत्पादन करेगा के एक inorder की पैदल दूरी के बाद से, एक ही विकल्प पेड़ चलने के लिए, रिकॉर्डिंग तत्वों की inorder अनुक्रम हमने पाया है, फिर ऊपर कलन विधि का उपयोग किया जाएगा। उदाहरण के लिए, अपने मूल BST पर विचार करें:

              20
         /         \
      15             30
     /   \         /   \ 
   10    17      25     33
  / |   /  \    /  \    |  \
9  16  12  18  22  26  31  34

हम एक सरणी में इस linearize, तो हम मिल

9 10 16 15 12 17 18 20 22 25 26 30 31 33 34

ध्यान दें कि 16 उसके आसपास के तत्वों से बड़ा है और है कि 12 अपने से कम है। यह तुरंत हमें बताता है कि 12 और 16 की अदला-बदली की गई।

इस समस्या को हल करने के लिए एक सरल एल्गोरिथ्म, इसलिए, एक तरह एक अनुक्रम में यह linearize को पेड़ की एक inorder की पैदल दूरी पर ऐसा करने के लिए किया जाएगा vectorया deque, तो उस अनुक्रम स्कैन करने के लिए सबसे बड़ा स्थानीय अधिकतम और सबसे छोटी स्थानीय न्यूनतम खोजने के लिए। यह हे (एन) समय में किये हैं, हे (एन) स्थान का उपयोग कर। वर्तमान नोड, अपने पूर्ववर्ती, और उसके उत्तराधिकारी - - करने के लिए एक बार में केवल तीन नोड्स का ट्रैक रखने के लिए एक जटिल काम है, लेकिन और अधिक स्थान की कुशल एल्गोरिथ्म होगा जो हे करने के लिए स्मृति के उपयोग को कम कर देता है (1)।

उम्मीद है की यह मदद करेगा!

31/08/2011 को 21:22
का स्रोत उपयोगकर्ता

वोट
0

पेड़ के द्वारा किया ट्रेवर्सल templatetypedef काम करता है अगर आप निश्चित केवल एक स्वैप है कर रहे हैं। अन्यथा मैं एक समाधान अपने प्रारंभिक कोड के आधार पर सुझाव देते हैं:

int GetMax(TreeNode* tree) {
    int max_right, max_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        max_left = GetMax(tree->left);
        if (max_left > ret)
            ret = max_left;
    }
    if (tree->right != NULL) {
        max_right = GetMax(tree->right);
        if (max_right > ret)
            ret = max_right;
    }

    return ret;
}

int GetMin(TreeNode* tree) {
    int min_right, min_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        min_left = GetMin(tree->left);
        if (min_left < ret)
            ret = min_left;
    }
    if (tree->right != NULL) {
        min_right = GetMin(tree->right);
        if (min_right < ret)
            ret = min_right;
    }

    return ret;
}

void print_violations(TreeNode* tree) {
    if ((tree->left != NULL) && (tree->right != NULL)) {
        int max_left = GetMax(tree->left);
        int min_right = GetMin(tree->right);
        if (max_left > tree->data && min_right < tree->data) {
            printf("Need to swap %d with %d\n", max_left, min_right);
        }
    }
    if (tree->left != NULL)
        print_violations(tree->left);
    if (tree->right != NULL)
        print_violations(tree->right);
}

यह धीमी है, लेकिन यह सब स्वैप यह पहचान करता प्रिंट करता है। सभी उल्लंघन (जैसे अगर (max_left> tree-> डेटा) प्रिंट उल्लंघन) मुद्रित करने के लिए बदला जा सकता है। आप प्रदर्शन में सुधार आप अधिकतम और न्यूनतम कि सबट्री के लिए precomputed साथ TreeNode के दो क्षेत्रों में जोड़ सकते हैं, तो कर सकते हैं।

01/09/2011 को 08:43
का स्रोत उपयोगकर्ता

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