बाइनरी ट्री रोटेशन

वोट
3

मैं एक AVL खोजें पेड़ लागू करने पर काम कर रहा हूँ। अब तक मैं कोडिंग हिस्सा समाप्त हो गया है और मैं कीड़े के लिए परीक्षण शुरू कर दिया है। मुझे पता चला कि मेरी नोड रोटेशन तरीकों bugged रहे हैं और भगवान की खातिर मैं नहीं समझ सकता समस्या क्या।

एल्गोरिथ्म के रूप में यह कागज पर होना चाहिए, लेकिन जब एक मशीन पर निष्पादित यह अच्छी तरह से ... लीक पेड़ नोड्स काम करता है।

यह बाईं ओर एक नोड बारी बारी से करने के लिए इस्तेमाल विधि है: http://pastebin.com/mPHj29Af

bool avl_search_tree::avl_tree_node::rotate_left()
{
    if (_right_child != NULL) {
        avl_tree_node *new_root = _right_child;
 
        if (_parent != NULL) {
            if (_parent->_left_child == this) {
                _parent->_left_child = new_root;
            } else {
                _parent->_right_child = new_root;
            }
        }
 
        new_root->_parent = _parent;
        _parent = new_root;
 
        _right_child = new_root->_left_child;
        new_root->_left_child = this;
 
        if (_right_child != NULL) {
            _right_child->_parent = this;
        }
 
        //update heights
        update_height();
        new_root->update_height();
 
        return true;
    }
 
    return false;
}

मेरी प्रविष्टि विधि में मैं हिस्सा संतुलन AVL टिप्पणी की है और बजाय मैं सिर्फ बाईं ओर नव डाला नोड को घुमाने के लिए कोशिश कर रहा हूँ। मेरी पेड़ केवल प्रारंभिक रूट (प्रथम नोड डाला) और अन्य सभी नोड्स लीक कर रहे हैं शामिल हैं: आरोही क्रम में पूर्णांकों डालने के लिए परिणाम।

समस्या की पहचान करने में किसी भी मदद अत्यधिक सराहना के रूप में मैं पागल हो जाने के लिए शुरू कर रहा है।

रिकॉर्ड के लिए: अगर मैं किसी भी रोटेशन का उपयोग नहीं करते पेड़ नोड्स लीक नहीं होगा और यह (प्रविष्टि और देखने के लिए) एक सामान्य असंतुलित द्विआधारी खोज वृक्ष के रूप में काम करता है।

संपादित करें: AJG85 की टिप्पणी के कारण मैं टिप्पणियों जोड़ देंगे:

मैं avl_search_tree :: avl_tree_node का नाशक विधि है कि avl_search_tree के डालने विधि है कि बस डाला गया कुंजी प्रिंट होगा करने के लिए सफाई से पहले कुंजी मान (मेरे मामले 32 बिट पूर्णांक में) प्रिंट होगा और, करने के लिए printf चेक 'जोड़ी गई।

फिर कार्यक्रम के entrypoint में मैं ढेर पर एक avl_search_tree आवंटित और आरोही क्रम में यह करने के लिए कुंजी जोड़ने और फिर इसे हटा दें।

AVL संतुलन सक्षम होने के साथ मैं टर्मिनल में निम्न उत्पादन मिलता है:

bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1

इसका मतलब है thatall सम्मिलन सफल रहे थे लेकिन केवल रूट हटा दिया गया है।

साथ AVL संतुलन बाहर टिप्पणी की यह एक सामान्य द्विआधारी खोज वृक्ष की तरह काम करता है। टर्मिनल आउटपुट है:

bool avl_search_tree::insert(const int&) : 1
bool avl_search_tree::insert(const int&) : 2
bool avl_search_tree::insert(const int&) : 3
bool avl_search_tree::insert(const int&) : 4
bool avl_search_tree::insert(const int&) : 5
bool avl_search_tree::insert(const int&) : 6
bool avl_search_tree::insert(const int&) : 7
bool avl_search_tree::insert(const int&) : 8
avl_search_tree::avl_tree_node::~avl_tree_node() : 1
avl_search_tree::avl_tree_node::~avl_tree_node() : 2
avl_search_tree::avl_tree_node::~avl_tree_node() : 3
avl_search_tree::avl_tree_node::~avl_tree_node() : 4
avl_search_tree::avl_tree_node::~avl_tree_node() : 5
avl_search_tree::avl_tree_node::~avl_tree_node() : 6
avl_search_tree::avl_tree_node::~avl_tree_node() : 7
avl_search_tree::avl_tree_node::~avl_tree_node() : 8

इसका मतलब है कि सब कुछ ठीक तरह से साफ किया जाता है।

अब ... कैसे मैं इस निष्कर्ष पर आया था कि रोटेशन तरीकों मुद्दों कर रहे हैं? टिप्पणी की AVL संतुलन सबरूटीन के तहत मैं एक पंक्ति है कि बाईं ओर हर हाल में डाला नोड घूमता गयी। परिणाम? एक ही AVL संतुलन सबरूटीन के रूप में यदि सक्षम किया गया था।

और विधि update_height () के बारे में, यह किसी भी तरह से पेड़ की संरचना में परिवर्तन नहीं करता।

मुझे आशा है कि यह यह स्पष्ट होगा।

संपादित करें 2:

कुछ और चीजों को स्पष्ट करने के लिए, उसकी कैसे avl_tree_node नाशक कार्यान्वित किया जाता है है:

avl_search_tree::avl_tree_node::~avl_tree_node()
{
    printf(%s : %d\n, __PRETTY_FUNCTION__, *_key);

    if (_left_child != NULL) {
        delete _left_child;
    }

    if (_right_child != NULL) {
        delete _right_child;
    }

    if (_key != NULL) {
        delete _key;
    }
}

_left_child और _right_child ढेर पर आवंटित वस्तुओं avl_tree_node के संकेत दिए गए हैं।

संपादित करें 3:

AGJ85 के 2 टिप्पणी के लिए धन्यवाद मैं इस मुद्दे पाया। मेरी घुमाने के तरीकों में मैं भूल गया मैं वास्तव में नया रूट करने के लिए पेड़ की जड़ सूचक अद्यतन करने के लिए जब भी जड़ स्थानांतरित कर दिया गया है।

मूल रूप से पेड़ की जड़ हमेशा पहले डाला नोड के लिए और सूचक जब जरूरत, मेरे घुमाने तरीकों नया पेड़ की जड़ जो वास्तव में सही कॉन्फ़िगर किया गया था रिसाव करेगा अपडेट किए बिना इशारा करते हुए किया गया था। :)

आप AGJ85 धन्यवाद!

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


3 जवाब

वोट
2

संपादित करें - अरे - मैं नहीं देखा था कि इस मुद्दे को पहले से ही हल किया जाता है (सवाल में जवाब)। फिर भी, शायद वहाँ इस लायक salvaging में कुछ गैर-जवाब सुझावों है।

मैं अच्छी तरह से जाँच नहीं की है, लेकिन मुझे लगता है कि आप इस लाइन पर गलत जा रहे हैं ...

_right_child = new_root->_left_child;

और समस्या यह है कि आप पहले से ही ओवरराइट हो सकता है कि new_root->_left_childलाइन में ...

_parent->_left_child = new_root;

क्या मुझे लगता है कि आपको क्या करना चाहिए है, शुरू में, जैसे स्थानीय परिभाषाओं का एक ब्लॉक है ...

avl_tree_node *orig_parent      = _parent;
avl_tree_node *orig_this        = this;
avl_tree_node *orig_left_child  = _left_child;
avl_tree_node *orig_right_child = _right_child;

तब का उपयोग orig_बाद में कार्य के लिए स्रोत के रूप में स्थानीय चर। इस डेटा के बारे में चिंता की एक निश्चित राशि रोटेशन के दौरान विभिन्न संकेत के माध्यम से प्रवाह को बचाता है। अनुकूलक इस में के बारे में चिंता के लायक किसी भी अनावश्यक काम से छुटकारा मिलना चाहिए, और वहाँ है कि वैसे भी ज्यादा नहीं है।

अतिरिक्त अंक के एक जोड़े ...

सबसे पहले, सी ++ (और सी) मानकों आरक्षित पहचानकर्ता प्रमुख अंडरस्कोर से, और डबल अंडरस्कोर से। यह दावा किया जाता है कि आप मानक और संकलक की आपूर्ति पुस्तकालयों के साथ आश्चर्य बातचीत प्राप्त कर सकते हैं यदि आप उस का सम्मान नहीं करते - मुझे लगता है कि है कि हालांकि, सदस्य पहचानकर्ता के लिए वृहद संबंधित होने के लिए होगा। पीछे चल अंडरस्कोर ठीक कर रहे हैं - मैं उन्हें इस्तेमाल करने के लिए गार्ड में शामिल करते हैं।

सदस्य चर के लिए एक आम सम्मेलन एक अग्रणी जोड़ना है mया m_। इससे भी अधिक आम है, शायद, किसी भी विशेष उपसर्ग या प्रत्यय बिल्कुल नहीं होने है।

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

अंत में, एक सामान्य टिप - "सूखी रन" इस तरह एक एल्गोरिथ्म आसानी से आप ट्रिप कर सकते हैं अप करने के लिए जब तक आप की कोशिश कर सख्ती से उसके बीच काम चरण दर चरण, और जानकारी के सभी स्रोतों कि प्रासंगिक हैं जाँच पर (मैं पहले से ही इस बदलाव कर दिया है?) हर कदम। यह गति के लिए विवरण में से कुछ लंघन की आदत में पाने के लिए बहुत आसान है। एक उपयोगी मशीन की मदद से सूखी रन एक डिबगर में कोड कदम-दर-कदम चलाने के लिए, और देखें कि क्या हर कदम पर परिणामों को अपने कागज सूखी रन से सहमत है।

संपादित करें - एक और टिप्पणी - मैं इस एक टिप फोन नहीं होगा, क्योंकि मैं इस संदर्भ में यकीन नहीं है। कोई डेटा छुपा, अगर कुछ किसी भी सदस्य कार्य - मैं आमतौर पर साधारण structs के साथ डेटा संरचना नोड्स को लागू। कोड के अधिकांश डेटा संरचना से अलग रखा जाता है, अक्सर एक "उपकरण" वर्ग में। मैं इस वर्ष "आकार में ही मिलती है" OOP सिद्धांत टूट जाता है पता है, लेकिन IMO यह व्यवहार में बेहतर काम करता है।

02/08/2011 को 20:34
का स्रोत उपयोगकर्ता

वोट
3

AGJ85 के 2 टिप्पणी के लिए धन्यवाद मैं इस मुद्दे पाया। मेरी घुमाने के तरीकों में मैं भूल गया मैं वास्तव में नया रूट करने के लिए पेड़ की जड़ सूचक अद्यतन करने के लिए जब भी जड़ स्थानांतरित कर दिया गया है।

मूल रूप से पेड़ की जड़ हमेशा पहले डाला नोड के लिए और सूचक जब जरूरत, मेरे घुमाने तरीकों नया पेड़ की जड़ जो वास्तव में सही कॉन्फ़िगर किया गया था रिसाव करेगा अपडेट किए बिना इशारा करते हुए किया गया था। :)

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

वोट
1

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

देखने के एक उच्च स्तर पर, तकनीक मैं के साथ समस्याओं से बचने के लिए उपयोग किया है AVL ट्री या लाल-काले ट्री कोड के बजाय एक प्रयोग है ए.ए. ट्री , जो उन्हें करने के लिए इसी तरह के प्रदर्शन है, हे (एन) अंतरिक्ष और ओ (प्रवेश का प्रयोग एन) सम्मिलित करने के लिए समय, हटाएं और खोजें। हालांकि, ए.ए. पेड़ काफी कोड के लिए आसान कर रहे हैं।

04/08/2011 को 16:55
का स्रोत उपयोगकर्ता

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