किसी लिंक की गई सूची से किसी आइटम को निकालने का सही तरीका


10

इस Slashdot साक्षात्कार में लिनुस टॉर्वाल्ड्स के रूप में उद्धृत किया गया है:

मैंने बहुत से लोगों को देखा है जो "प्रचलित" प्रविष्टि पर नज़र रखते हुए एक एकल-लिंक्ड सूची प्रविष्टि को हटाते हैं, और फिर प्रविष्टि को हटाने के लिए कुछ ऐसा करते हैं

if (
  प्रचलित ) prev-> अगला = प्रविष्टि-> अगला;
अन्य
  सूची_हेड = प्रविष्टि-> अगला;

और जब भी मुझे उस तरह का कोड दिखाई देता है, मैं बस "यह व्यक्ति संकेत नहीं समझता"। और यह काफी दुख की बात है।

जो लोग पॉइंटर्स को समझते हैं, वे "एंट्री पॉइंटर को पॉइंटर" का उपयोग करते हैं, और लिस्ट_हेड के पते के साथ इसे इनिशियलाइज़ करते हैं। और फिर जैसे ही वे सूची को आगे बढ़ाते हैं, वे केवल "* पीपी = प्रविष्टि-> अगला" करके, किसी भी शर्त का उपयोग किए बिना प्रविष्टि को हटा सकते हैं।

एक PHP डेवलपर के रूप में मैंने एक दशक पहले विश्वविद्यालय में सी के परिचय के बाद से संकेत नहीं छुआ है । हालांकि, मुझे लगता है कि यह एक प्रकार की स्थिति है जिससे मुझे कम से कम परिचित होना चाहिए। लिनस किस बारे में बात कर रहा है? ईमानदार होने के लिए, अगर मुझे एक लिंक की गई सूची को लागू करने और एक आइटम को हटाने के लिए कहा गया, तो उपरोक्त 'गलत' तरीका है कि मैं इसके बारे में जाऊंगा। जैसा कि लिनुस सबसे अच्छा कहता है, मुझे कोड करने के लिए क्या जानना चाहिए?

मैं स्टैक ओवरफ्लो के बजाय यहां पूछ रहा हूं क्योंकि मैं वास्तव में उत्पादन कोड में इसके साथ कोई समस्या नहीं है।


1
वह जो कह रहा है वह यह है कि जब आपको prevपूरे नोड को संग्रहीत करने के बजाय स्थान को संग्रहीत करने की आवश्यकता होती है , तो आप बस के स्थान को संग्रहीत कर सकते हैं prev.next, क्योंकि केवल वही चीज है जिसमें आप रुचि रखते हैं। एक सूचक के लिए एक सूचक। और अगर आप ऐसा करते हैं, तो आप मूर्खतापूर्ण से बचते ifहैं, क्योंकि अब आपके पास list_headएक नोड के बाहर से एक पॉइंटर होने का अजीब मामला नहीं है । सूची के प्रमुख के लिए सूचक तब शब्दार्थ है जो कि अगले नोड के सूचक के समान है।
साधारण

@ अच्छा: मैं देख रहा हूँ, धन्यवाद। टिप्पणी क्यों? यह एक स्पष्ट, स्पष्ट और प्रकाशित जवाब है।
डॉटनचेन

@ उस कोड स्निपेट में शामिल हर चीज एक पॉइंटर होती है, इसलिए उसकी बात का पूरा नोड बनाम स्टोर करने का कोई संकेत नहीं हो सकता है।
डोभाल

जवाबों:


9

मेरे L331 एमएस पेंट कौशल का उपयोग करना:

यहां छवि विवरण दर्ज करें

मूल समाधान के माध्यम से नोड्स को इंगित करना है curr। उस स्थिति में आप चेक करते हैं currकि डिलीट वैल्यू के बाद अगला नोड है या नहीं , और यदि currनोड nextपॉइंटर को रीसेट किया जाए । समस्या यह है कि कोई नोड नहीं है जो सूची के प्रमुख को इंगित करता है। इसका मतलब है कि इसे जांचने के लिए एक विशेष मामला होना चाहिए।

इसके बजाय लिनुस (संभावना) प्रस्तावित करता है कि सूचक को वर्तमान परीक्षित नोड में सहेजना नहीं है, बल्कि पॉइंटर को पॉइंटर को वर्तमान नोड (लेबल pp) में रखना है । ऑपरेशन समान है - यदि ppपॉइंटर सही मान के साथ नोड को इंगित करता है, तो आप ppपॉइंटर को रीसेट करते हैं ।

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


आह मैं अब देख रहा हूँ .... आप हर दिन कुछ नया सीखते हैं।
लॉरेंस आइलो

1
मुझे लगता है कि आप चीजों को सही ढंग से वर्णित करते हैं, लेकिन मैं सुझाव दूंगा कि उचित समाधान list_headएक nextनोड के साथ कुछ करने के लिए इंगित करता है जो पहले वास्तविक डेटा आइटम की ओर इशारा करता है (और prevउसी डमी ऑब्जेक्ट के लिए प्रारंभिक है)। मुझे prevकुछ अलग प्रकार के बिंदु होने का विचार पसंद नहीं है , क्योंकि इस तरह की चालें अलफ़ाइंग के माध्यम से अपरिभाषित व्यवहार का परिचय दे सकती हैं, और कोड को संरचना लेआउट के लिए अनावश्यक रूप से संवेदनशील बना सकती हैं।
सुपरकैट

@ सुपरपैक्ट बिल्कुल यही बात है। prevनोड्स की ओर इशारा करने के बजाय , यह इंगित करता है। यह हमेशा एक ही प्रकार के कुछ को इंगित करता है, अर्थात् एक नोड को सूचक। आपका सुझाव अनिवार्य रूप से एक ही है - prevकुछ बिंदु "एक nextनोड के साथ " है। यदि आप शेल को छोड़ देते हैं तो आपको शुरुआती list_headपॉइंटर मिलता है । या दूसरे शब्दों में - कुछ जो केवल अगले नोड के लिए एक संकेतक होने से परिभाषित किया गया है, शब्दार्थ एक नोड के लिए सूचक के बराबर है।
आयुध

@Ordous: यह समझ में आता है, हालांकि यह उसको निर्धारित करता है list_headऔर nextपॉइंटर के समान "प्रकार" को धारण करेगा। सी में कोई मुद्दा नहीं, शायद, लेकिन सी + + में शायद समस्याग्रस्त।
सुपरकैट

@supercat मैंने हमेशा माना कि एक लिंक की गई सूची, भाषा-अज्ञेय का "कैनोनिकल" प्रतिनिधित्व है। लेकिन मैं न्याय करने के लिए पर्याप्त कुशल नहीं हूं कि क्या यह वास्तव में सी और सी ++ के बीच अंतर करता है, और वहां मानक कार्यान्वयन क्या हैं।
आयुध

11

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

कोड उदाहरण

// ------------------------------------------------------------------
// Start by pointing to the head pointer.
// ------------------------------------------------------------------
//    (next_ptr)
//         |
//         v
// [head]----->[..]----->[..]----->[..]----->[to_remove]----->[....]
Node** next_ptr = &list->head;

// ------------------------------------------------------------------
// Search the list for the matching entry.
// After searching:
// ------------------------------------------------------------------
//                                  (next_ptr)
//                                       |
//                                       v
// [head]----->[..]----->[..]----->[..]----->[to_remove]----->[next]
while (*next_ptr != to_remove) // or (*next_ptr)->val != to_remove->val
{
    Node* next_node = *next_ptr
    next_ptr = &next_node->next;
}

// ------------------------------------------------------------------
// Dereference the next pointer and set it to the next node's next
// pointer.
// ------------------------------------------------------------------
//                                           (next_ptr)
//                                                |
//                                                v
// [head]----->[..]----->[..]----->[..]---------------------->[next]
*next_ptr = to_remove->next;

यदि हमें नोड को नष्ट करने के लिए कुछ तर्क की आवश्यकता है, तो हम अंत में कोड की एक पंक्ति जोड़ सकते हैं:

// Deallocate the node which is now stranded from the list.
free(to_remove);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.