2011-08-06 8 views
8

मेरे वर्तमान शिक्षण अभ्यास के लिए, मैं लिंक्ड सूचियों और पेड़ों का अध्ययन कर रहा हूं। मैंने हाल ही में प्रत्येक नोड को अपने बच्चे/बच्चों को हटाकर डेटा संरचनाओं को दोबारा नष्ट करने के लिए एक सुझाव देखा। हालांकि मुझे पता चला है कि लगभग सभी उदाहरणों में, नोड विनाशक खाली है और कुछ प्रबंधन वर्ग पुनरावृत्ति के कुछ रूपों का उपयोग करके विनाश को नियंत्रित करता है और हटा देता है। एक विश्वसनीयता और/या स्टाइलिस्ट परिप्रेक्ष्य से, क्या पुनरावर्ती विनाशक के बारे में कुछ भी स्वाभाविक रूप से बुरा है?क्या जुड़ी हुई सूची, पेड़, आदि के लिए एक पुनरावर्ती विनाशक खराब है?

दो दृष्टिकोणों की मेरी समझ के कार्यान्वयन का मेरा अनुसरण क्या है।

रिकर्सिव विनाश:

#include <iostream> 
struct Node { 
    static int count; 
    Node() : num_(count++), p_next_(0) {} 
    ~Node() { 
    std::cout << "entering " << num_ << "\n"; 
    delete p_next_; 
    std::cout << " leaving " << num_ << "\n"; 
    } 
    const int num_; 
    Node* p_next_; 
}; 
int Node::count = 0; 
int main() { 
    Node* p_head = new Node(); 
    p_head->p_next_ = new Node(); 
    p_head->p_next_->p_next_ = new Node(); 
    delete p_head; 
    return 0; 
} 

और यहाँ प्रबंध वर्ग से निपटने विनाश पर मेरी ले रहा है। मान लें मैं नोड के लिए निम्नलिखित DTOR परिभाषित किया था:

~Node() {std::cout << "Someone deleted " << num_ << "\n";} 

मैं परिभाषित करेगा निम्नलिखित LinkedList प्रबंध वर्ग और बाद में मुख्य

/* other stuff from above */ 
class LinkedList { 
public: 
    LinkedList() : p_head_(new Node()) { 
    p_head_->p_next_ = new Node(); 
    p_head_->p_next_->p_next_ = new Node(); 
    } 
    ~LinkedList() { 
    while(Node* p_prev = p_head_) { 
     p_head_ = p_head_->p_next_; 
     delete p_prev; 
    } 
    } 
private: 
    Node* p_head_; 
}; 
int main() { 
    LinkedList* p_list = new LinkedList(); 
    delete p_list; 
    return 0; 
} 

मान लिया जाये कि मैं अपने परिणामों को सही ढंग से पढ़ रहा हूँ, मेरे दो कार्यान्वयन भी ऐसा ही चीज़।

मेरी पुनरावर्ती विनाश उदाहरण के संबंध में

, मुझे लगता है कि मैं लगभग हमेशा के प्रबंधन वर्ग के कुछ प्रकार जब मैं कोड के साथ एक वास्तविक समस्या को सुलझाने रहा है कि सिर की एक प्रति रखती आवश्यकता होगी, लेकिन प्रबंध वर्ग केवल सिर हटाना होगा/संपूर्ण नोड संरचना के विनाश को सुनिश्चित करने के लिए रूट नोड। यह मेरे लिए अधिक सुरुचिपूर्ण लगता है, लेकिन मुझे कोड के साथ परेशानी हो गई है जो मैंने सोचा था कि साफ था।

क्या प्रबंधन वर्ग यह सुनिश्चित करने के लिए ज़िम्मेदार होना चाहिए कि सब कुछ ठीक से हटा दिया जाए? या अंतर्निहित डेटा संरचना के लिए यह बेहतर है कि यह कैसे साफ हो जाए? क्या कोई गठिया है जो स्पष्ट नहीं है?

धन्यवाद!

- जोर्डन

संपादित करें: मुझे एक विचार हुआ। अगर मेरे पास नोड्स की एक लंबी श्रृंखला है, तो मुझे पहले उदाहरण में विनाश के दौरान एक स्टैक ओवरफ्लो के बारे में चिंता करने की ज़रूरत है क्योंकि रिकर्सन खेल रहा है?

संपादित 2: मुझे लगता है कि यह स्पष्ट होना चाहिए था। और अब मैं बस थोड़ा मूर्ख महसूस करता हूँ। मेरी मशीन पर, अगर मेरे पास 64 9 10 से अधिक नोड्स हैं, तो मैं क्रैश हो जाता हूं। तो रिकर्सन स्पष्ट रूप से एक गॉचा प्रस्तुत करता है।

+1

हां, आपके पहले दृष्टिकोण के खिलाफ मुख्य तर्क यह तथ्य है कि कई नोड्स वाली एक सूची वास्तव में एक स्टैक ओवरफ़्लो का कारण बन सकती है, भले ही एक अच्छा कंपाइलर यह समझने में सक्षम हो कि आपको प्रत्येक के लिए अतिरिक्त स्टैक स्पेस की आवश्यकता नहीं है कॉल करें, क्योंकि आपके लिए कार्य करने के लिए कोई वापसी परिणाम नहीं हैं। –

+0

लेकिन मुझे लगता है कि एक अच्छा संकलक पर भरोसा करना सुरक्षित नहीं है? –

+1

आप फिर से सही हैं। ऐसी भाषाएं हैं जहां पुनरावृत्ति पुनरावृत्ति के लिए मुख्य उपकरण है और जहां आपको गारंटी है कि एक समान दृष्टिकोण संसाधनों को बर्बाद नहीं करता है। हालांकि यह सी ++ –

उत्तर

6

यदि आप लिंक की गई सूचियों के लिए ऐसा करते हैं तो एक स्टैक मेमोरी खपत समस्या होगी।इस तरह की एक लिंक्ड सूची को नष्ट करने से आपके Node का रिकर्सिव डीओ टोर होगा, जबकि रिकर्सन गहराई आपकी लिंक्ड सूची के आकार के साथ रैखिक रूप से बढ़ेगी।

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

ओटीओएच पेड़ के लिए ऐसा करने से कम से कम तकनीकी परिप्रेक्ष्य से ठीक है। वृक्ष सफाई आमतौर पर वैसे भी लागू होती है, भले ही उपरोक्त रिकर्सिव फ़ंक्शन पेड़ से संबंधित हो या Node महत्वपूर्ण नहीं है।

वृक्ष को नष्ट करने की पुनरावृत्ति गहराई पेड़ की गहराई के साथ लॉगरिदमिक रूप से बढ़ेगी, जो ठीक है।

4

लिंक किए गए आइटम के स्वामित्व के बारे में सोचें।

क्या यह समझ में आता है कि एक नोड ऑब्जेक्ट अगले केन का मालिक है? यह निश्चित रूप से समझ में आता है कि एक नोड संलग्न उपग्रह डेटा का मालिक है, इसलिए जब आपको नोड नष्ट किया जा रहा है तो आपको इसे साफ़ करना चाहिए।

लिंक्डलिस्ट के नोड्स का मालिक है, इसलिए इसे किसी भी मेमोरी-बचे हुए बिना ठीक से नष्ट करने के लिए जिम्मेदार होना चाहिए।

लिंक्डलिस्ट ऑब्जेक्ट नोड्स को जोड़ने और निकालने में सक्षम होना चाहिए, इसलिए स्वामित्व बिंदु से, यह सूची में प्रत्येक नोड को हटाकर उदाहरण के लिए उन्हें साफ़ करने के लिए ज़िम्मेदार है।

+0

तो क्या आपको यह सुझाव देना है कि बी/सी प्रबंधन वर्ग को लिंक किए गए नोड्स द्वारा गठित अंतर्निहित डेटा संरचना का मालिक है, यह नोड को क्लीन-अप कार्यक्षमता देने के लिए भ्रमित/खराब रूप है? –

+2

यह आम तौर पर नहीं, लेकिन एक नोड के लिए यह दावा है। इसे देखें: लिंक्डलिस्ट के पास नोड्स हैं, इसलिए लिंक्डलिस्ट उन्हें मुक्त करने के लिए ज़िम्मेदार है जब सूची हटाई जाती है और विनाशक को बुलाया जाएगा। नोड के लिए एक ही नियम होता है और एक नोड अपने उपग्रह डेटा को नष्ट करने के लिए ज़िम्मेदार होता है - लेकिन कोई अन्य नोड जो यह लिंक करता है, क्योंकि इन नोड्स (अगली और पिछली) नोड द्वारा स्वामित्व वाले _not_ हैं लेकिन लिंक्डलिस्ट द्वारा – Wizz

संबंधित मुद्दे