ऐरे बनाम लिंक्ड-लिस्ट


200

कोई सरणी से अधिक लिंक-सूची का उपयोग क्यों करना चाहेगा?

लिंक्ड-लिस्ट को कोड करना, कोई संदेह नहीं है, एक सरणी का उपयोग करने की तुलना में थोड़ा अधिक काम है और कोई आश्चर्यचकित हो सकता है कि अतिरिक्त प्रयास को क्या औचित्य देगा।

मुझे लगता है कि नए तत्वों का सम्मिलन एक लिंक्ड-लिस्ट में तुच्छ है, लेकिन यह एक सरणी में एक प्रमुख कोर है। क्या डेटा के एक सेट को स्टोर करने के लिए लिंक की गई सूची का उपयोग करने के लिए अन्य फायदे हैं?

इस सवाल का डुप्लिकेट नहीं है इस सवाल है क्योंकि अन्य प्रश्न किसी विशेष जावा वर्ग के बारे में विशेष रूप से पूछ रहा है, जबकि इस सवाल का सामान्य डेटा संरचनाओं के साथ संबंध है।


1
संबंधित - जब ArrayList <> पर LinkedList <> का उपयोग करना है? - यह जावा है, लेकिन arrays (ArrayList) और लिंक्ड-सूचियों का संभवतः किसी भी भाषा में समान प्रदर्शन है।
बर्नहार्ड बार्कर


1
@rootTraveller वास्तव में यह प्रश्न इस प्रश्न का दोहराव होगा क्योंकि मेरा प्रश्न पहले पोस्ट किया गया था।
ओनोरियो कैटेनेशिया

जवाबों:


147
  • लिंक की गई सूची में विभिन्न आकारों के डेटा को संग्रहीत करना आसान है। एक सरणी मानती है कि हर तत्व समान आकार का है।
  • जैसा कि आपने उल्लेख किया है, यह एक लिंक्ड सूची के लिए व्यवस्थित रूप से बढ़ना आसान है। किसी सरणी के आकार को समय से पहले जाना जाता है, या इसे विकसित करने की आवश्यकता होने पर पुनः बनाया जाता है।
  • लिंक की गई सूची में फेरबदल करना सिर्फ इस बात को बदलने का विषय है कि क्या इंगित करता है। एक सरणी फेरबदल अधिक जटिल है और / या अधिक स्मृति लेता है।
  • जब तक आपके पुनरावृत्तियों सभी एक "foreach" संदर्भ में होते हैं, तब तक आप पुनरावृति में कोई प्रदर्शन नहीं खोते हैं।

19
विभिन्न आकारों की वस्तुओं को किसी भी अलग तरह से कैसे व्यवहार किया जाता है? एक लिंक की गई सूची या तो एक अगले क्षेत्र के साथ एक निश्चित संरचना का उपयोग करती है (निश्चित आकार की आवश्यकता होती है), या कार में डेटा के लिए एक पॉइंटर को संग्रहीत करता है (चर आकार ठीक)। दोनों दृष्टिकोण एक वेक्टर के साथ आसान हैं। फेरबदल के लिए भी यही।
ब्रायन

32
मैं कहूंगा कि एक सरणी फेरबदल करना कम जटिल है।
ह्यूग एलन

23
यह उत्तर गलत और भ्रामक है। (जब आप इसे घोषित करते हैं तो एक सरणी के आकार को जानने की आवश्यकता को छोड़कर)
रॉबर्ट पॉलसन

35
डेटा स्थानीयता के कारण लिंक की गई सूची की पुनरावृति धीमी नहीं होगी?
फिरास असद

6
@ रिक, वैक्टर आम तौर पर उस स्थान को समग्र रूप से आवंटित करते हैं, जिसकी उन्हें आवश्यकता होती है, ताकि आकार बढ़ने पर उन्हें नई जगह आवंटित करने की आवश्यकता न हो। इसका परिणाम यह है कि वैक्टर आम तौर पर बहुत कम मेमोरी इंटेंसिव होते हैं, न कि फिर लिस्टेड लिंक्ड।
विंस्टन एवर्ट

179

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

एक लिंक की गई सूची के साथ, पुनरावृत्तियां सूची में बदलाव कर सकती हैं जबकि संशोधन हो रहे हैं। आशावादी मामले में जहां संशोधन टकराते नहीं हैं, पुनरावृत्तियां विवाद के बिना जारी रह सकती हैं।

एक सरणी के साथ, सरणी के आकार को संशोधित करने वाले किसी भी परिवर्तन के लिए सरणी के एक बड़े हिस्से को लॉक करने की आवश्यकता होती है और वास्तव में, यह दुर्लभ है कि यह पूरे सरणी में एक वैश्विक लॉक के बिना किया जाता है इसलिए संशोधन विश्व मामलों को रोकते हैं।


9
एलेक्स - यह एक दिलचस्प विचार है जो मेरे साथ कभी नहीं हुआ होगा। बहुत अच्छा जवाब। अगर मैं कर सकता तो मैं आपको दो बार अपवोट करता। :-)
ओनोरियो कैटेनियास

5
जहाँ आप इस के साथ जा सकते हैं, एक अच्छे विचार के लिए स्किप लिस्ट (जावा 6 में विशेष रूप से समसामयिकी सूची में देखें)। CSLM उत्कृष्ट प्रदर्शन के साथ एक क्रमबद्ध, समवर्ती नक्शा है। सुदूर, एक सिंक्रनाइज़ ट्रीपैप से कहीं बेहतर। tech.puredanger.com/2007/10/03/skip-lists
एलेक्स मिलर

... सिवाय इसके कि ConcurrentSkipListMapया ConcurrentSkipListMap, सूची में नहीं हैं, भले ही "सूची" उनके नाम में कहीं होता है। दोनों को कुंजी की आवश्यकता होती है जो क्रमबद्ध और अद्वितीय होगी। यदि आपको एक List, यानी कि डेटा संरचना की आवश्यकता होती है जो एक मनमाना क्रम में डुप्लिकेट तत्वों की अनुमति देता है, तो यह उपयुक्त नहीं है और आपको LinkedListसमवर्ती updatable चीज़ जैसी डेटा संरचना बनाने के लिए महान लंबाई पर जाना होगा । यदि आपको केवल एक समवर्ती कतार या मृग की आवश्यकता है, तो ठीक है, हाँ, मौजूदा उदाहरण भी हैं, लेकिन समवर्ती List... मुझे यकीन नहीं है कि यह भी संभव है।
होल्गर

128

विकिपीडिया में मतभेदों के बारे में बहुत अच्छा खंड है।

लिंक किए गए सूचियों में सरणियों पर कई फायदे हैं। तत्वों को अनिश्चित रूप से लिंक की गई सूचियों में डाला जा सकता है, जबकि एक सरणी अंततः या तो भर जाएगी या उन्हें आकार बदलने की आवश्यकता होगी, एक महंगा ऑपरेशन जो स्मृति के खंडित होने पर भी संभव नहीं हो सकता है। इसी तरह, एक ऐसा सरणी जिसमें से कई तत्व निकाले जाते हैं, बेकार हो सकते हैं या उन्हें छोटा करने की आवश्यकता होती है।

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

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

http://en.wikipedia.org/wiki/Linked_list


4
यह एकदम सही जवाब है। सफलतापूर्वक दोनों के फायदे और नुकसान का वर्णन करता है।
रिक

धन्यवाद))) मृत सरल लेकिन मैंने इसे विकी में नहीं देखा है)
तैमूर फ़ेज़्रख्मनोव

58

मैं एक और जोड़ूंगा - सूचियां विशुद्ध रूप से कार्यात्मक डेटा संरचनाओं के रूप में कार्य कर सकती हैं ।

उदाहरण के लिए, आपके पास समान अंत अनुभाग को साझा करने वाली पूरी तरह से भिन्न सूचियाँ हो सकती हैं

a = (1 2 3 4, ....)
b = (4 3 2 1 1 2 3 4 ...)
c = (3 4 ...)

अर्थात:

b = 4 -> 3 -> 2 -> 1 -> a
c = a.next.next  

डेटा की प्रतिलिपि के बिना द्वारा की ओर इशारा किया जा रहा है aमें bऔर c

यही कारण है कि वे कार्यात्मक भाषाओं में इतने लोकप्रिय हैं, जो अपरिवर्तनीय चर का उपयोग करते हैं - prependऔर tailसंचालन मूल डेटा की नकल के बिना स्वतंत्र रूप से हो सकता है - बहुत महत्वपूर्ण विशेषताएं जब आप डेटा को अपरिवर्तनीय मान रहे हैं।


4
फिर भी एक और बहुत दिलचस्प विचार है कि मैं कभी नहीं आया हूँ। धन्यवाद।
ओनोरियो कैटेनेशिएक

मैं अजगर में यह कैसे कर सकता हूं?
21

29

सूची के बीच में डालने के अलावा आसान किया जा रहा है - यह एक सरणी की तुलना में लिंक की गई सूची के बीच से हटाना बहुत आसान है।

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


2
बहुत सही, सम्मिलन और विलोपन ज्यादातर समय की खोज के बाद होता है, इसलिए समय की जटिलताओं पर भी विचार करना होगा।
एमए हुसैन टोनू

28

दो लिंक की गई सूचियों (विशेष रूप से दो दोगुनी लिंक्ड सूचियों) को विलय करना दो सरणियों (विलय को विनाशकारी है) को विलय करने की तुलना में बहुत तेज है। पूर्व O (1) लेता है, बाद वाला O (n) लेता है।

संपादित करें: स्पष्ट करने के लिए, मेरा मतलब यहां "विलय" करना था, जो कि अव्यवस्थित अर्थ में था, न कि विलय के रूप में। शायद "कंक्रीटिंग" एक बेहतर शब्द होता।


2
केवल तभी जब आप एक सूची को दूसरे में जोड़ रहे हों। यदि आप वास्तव में दो क्रमबद्ध सूचियों का विलय कर रहे हैं तो यह O (1) से अधिक लॉग लेगा।
हर्म्स

3
@ अंक, लेकिन आप किसी भी अतिरिक्त मेमोरी को आवंटित किए बिना दो सॉर्ट की गई सूचियों को मर्ज कर सकते हैं, बस दोनों सूचियों का पता लगा सकते हैं और उचित रूप से पॉइंटर्स सेट कर सकते हैं। दो सरणियों को मिलाते हुए सामान्य रूप से कम से कम एक अतिरिक्त सरणी लेते हैं।
पॉल टॉम्बलिन

1
हां, सूचियों का विलय अधिक स्मृति कुशल है, लेकिन यह वास्तव में वह नहीं था जिस पर मैं टिप्पणी कर रहा था। लिंकिंग सूचियों को मर्ज करना O (1) मामले के स्पष्टीकरण के बिना बहुत भ्रामक है।
हर्म्स

@ हर्म्स मर्जिंग लिस्ट किसी भी समझदार डेटा मॉडल के तहत ऐरे को मर्ज करने से ज्यादा मेमोरीफुल नहीं है।
अलेक्सी एवरचेंको सेप

2
अलेक्सी एवेर्चेन्को: दो सूचियों को समेटते हुए, या यहां तक ​​कि मर्ज-छंटनी वाली दो छंटनी सूचियों को, ओ (1) मेमोरी के साथ किया जा सकता है। दो सरणियों को समेटने में O (n) मेमोरी आवश्यक हो जाती है, जब तक कि एरे को मेमोरी में पहले से ही न रखा गया हो। मुझे लगता है कि आप जिस बिंदु पर लक्ष्य कर रहे हैं वह यह है कि जहां n तत्वों की सूची और n तत्वों की एक सरणी दोनों O (n) मेमोरी लेते हैं, लेकिन लिंक की गई सूचियों के लिए गुणांक अधिक है।
रैंपियन

17

ArrayList के लिए और LinkedList के खिलाफ एक व्यापक रूप से अप्रयुक्त तर्क यह है कि LinkedLists डीबग करते समय असहज होते हैं । रखरखाव डेवलपर्स द्वारा कार्यक्रम को समझने के लिए बिताया गया समय, जैसे कि बग, वृद्धि और आईएमएचओ को खोजने के लिए, कभी-कभी प्रदर्शन में सुधार या एंटरप्राइज़ एप्लिकेशंस में मेमोरी खपत में बाइट्स को उचित नहीं ठहराता है। कभी-कभी (ठीक है, निश्चित रूप से यह अनुप्रयोगों के प्रकार पर निर्भर करता है), यह कुछ बाइट्स को बर्बाद करने के लिए बेहतर है, लेकिन एक ऐसा एप्लिकेशन है जो अधिक रखरखाव योग्य या समझने में आसान है।

उदाहरण के लिए, एक जावा वातावरण में और ग्रहण डिबगर का उपयोग करके, एक ArrayList डिबगिंग से संरचना को समझने में बहुत आसान पता चलेगा:

arrayList   ArrayList<String>
  elementData   Object[]
    [0] Object  "Foo"
    [1] Object  "Foo"
    [2] Object  "Foo"
    [3] Object  "Foo"
    [4] Object  "Foo"
    ...

दूसरी ओर, लिंक्डलिस्ट की सामग्री को देखने और विशिष्ट वस्तुओं को खोजने के लिए दुःस्वप्न का विस्तार-द-ट्री क्लिक हो जाता है, लिंक्डलिस्ट इंटीरियर को फ़िल्टर करने के लिए आवश्यक संज्ञानात्मक ओवरहेड का उल्लेख नहीं करने के लिए:

linkedList  LinkedList<String>
    header  LinkedList$Entry<E>
        element E
        next    LinkedList$Entry<E>
            element E   "Foo"
            next    LinkedList$Entry<E>
                element E   "Foo"
                next    LinkedList$Entry<E>
                    element E   "Foo"
                    next    LinkedList$Entry<E>
                    previous    LinkedList$Entry<E>
                    ...
                previous    LinkedList$Entry<E>
            previous    LinkedList$Entry<E>
        previous    LinkedList$Entry<E>

17

सबसे पहले, सी ++ से जुड़ी-सूचियों में एक सरणी से काम करने के लिए अधिक परेशानी नहीं होनी चाहिए। आप लिंक्ड सूची के लिए std :: सूची या बूस्टर पॉइंटर सूची का उपयोग कर सकते हैं । लिंक किए गए सूचियों बनाम सरणियों के साथ प्रमुख मुद्दे अतिरिक्त स्थान इंगित करने वाले और भयानक यादृच्छिक अभिगम के लिए आवश्यक हैं। यदि आप एक लिंक्ड सूची का उपयोग करना चाहिए

  • आपको डेटा तक यादृच्छिक पहुँच की आवश्यकता नहीं है
  • आप तत्वों को जोड़ना / हटाना होगा, विशेष रूप से सूची के बीच में

14

मेरे लिए यह इस तरह है,

  1. पहुंच

    • लिंक की गई सूचियां केवल तत्वों तक अनुक्रमिक पहुंच की अनुमति देती हैं। इस प्रकार एल्गोरिथम जटिलता O (n) का क्रम है
    • Arrays अपने तत्वों तक यादृच्छिक पहुँच की अनुमति देता है और इस प्रकार जटिलता O (1) का क्रम है।
  2. भंडारण

    • लिंक की गई सूचियों को संदर्भों के लिए अतिरिक्त संग्रहण की आवश्यकता होती है। यह उन्हें छोटे डेटा आइटम जैसे वर्ण या बूलियन मान की सूची के लिए अव्यावहारिक बनाता है।
    • Arrays को अगले डेटा आइटम को इंगित करने के लिए अतिरिक्त संग्रहण की आवश्यकता नहीं है। प्रत्येक तत्व को अनुक्रमित के माध्यम से पहुँचा जा सकता है।
  3. आकार

    • लिंक्ड सूचियों का आकार स्वभाव से गतिशील है।
    • सरणी का आकार घोषणा तक ही सीमित है।
  4. प्रविष्टि / हटाने की

    • तत्वों को लिंक किए गए सूचियों में अनिश्चित काल तक डाला और हटाया जा सकता है ।
    • सरणियों में मानों का सम्मिलन / विलोपन बहुत महंगा है। इसके लिए मेमोरी रियलाइजेशन की आवश्यकता होती है।

आपके पास 2 नंबर 2, और 2 नंबर 3 :)
हेंगामेह

हम एक खाली सरणी की घोषणा कर सकते हैं और फिर आवश्यकतानुसार डेटा जोड़ते रह सकते हैं। यह अभी भी एक निश्चित आकार कैसे बनाता है?
हेलेव

11

दो चीज़ें:

लिंक की गई सूची को कोड करना, कोई संदेह नहीं है, एक सरणी का उपयोग करने की तुलना में थोड़ा अधिक काम है और उसने सोचा कि अतिरिक्त प्रयास का क्या औचित्य होगा।

C ++ का उपयोग करते समय लिंक की गई सूची को कभी भी कोड न करें। बस एसटीएल का उपयोग करें। इसे लागू करना कितना कठिन है, कभी भी एक डेटा संरचना को दूसरे पर चुनने का कारण नहीं होना चाहिए क्योंकि अधिकांश पहले से ही वहां लागू हैं।

एक सरणी और एक लिंक की गई सूची के बीच वास्तविक अंतर के लिए, मेरे लिए बड़ी बात यह है कि आप संरचना का उपयोग करने की योजना कैसे बनाते हैं। मैं सदिश शब्द का उपयोग करूंगा क्योंकि यह C ++ में एक resizable सरणी के लिए पद है।

लिंक की गई सूची में अनुक्रमण धीमा है क्योंकि आपको दी गई अनुक्रमणिका में जाने के लिए सूची को पीछे करना होगा, जबकि एक वेक्टर स्मृति में सन्निहित है और आप सूचक गणित का उपयोग करके वहां पहुंच सकते हैं।

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

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


जैसा कि मैंने ऊपर किसी को बताया था, मैं सिर्फ उस सवाल को संबंधित करने की कोशिश कर रहा था जिस तरह से इसे मेरे सामने रखा गया था। मैं कभी भी C ++ में किसी सरणी (या रोल-माय-लिंक्ड लिस्ट) का उपयोग नहीं करूंगा - मैं उन दोनों के एसटीएल संस्करणों का उपयोग करूंगा।
ओनोरियो कैटेनेशिएक

10

एरिक लिपर्ट ने हाल ही में एक कारण पर एक पोस्ट किया था सरणियों का उपयोग रूढ़िवादी रूप से किया जाना चाहिए।


2
मोटे तौर पर एक अच्छी पोस्ट है, लेकिन लिंक की गई सूची बनाम सरणी की चर्चा में प्रासंगिक नहीं है।
रॉबर्ट पॉलसन

2
मेरा सुझाव है कि एरिक का अधिकांश लेख प्रासंगिक है, क्योंकि यह सरणियों के नुकसान और सूची के फायदे दोनों पर चर्चा करता है, सूची कार्यान्वयन के बावजूद।
बेवन

8

तेजी से सम्मिलन और निष्कासन वास्तव में लिंक किए गए सूचियों के लिए सर्वश्रेष्ठ तर्क हैं। यदि आपकी संरचना गतिशील रूप से बढ़ती है और किसी भी तत्व के लिए निरंतर-समय तक पहुंच की आवश्यकता नहीं होती है (जैसे गतिशील स्टैक और कतारें), तो लिंक की गई सूची एक अच्छा विकल्प है।


7

यहाँ एक त्वरित है: वस्तुओं को हटाना जल्दी है।


7

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


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

3
और एक "परिपत्र बफर" कहा जाता है, अगर आप इसे अपने पसंदीदा एल्गोरिदम संदर्भ में देखना चाहते हैं।
स्टीव जेसप

7

सूची के मध्य से जोड़ने और हटाने के अलावा, मैं लिंक की गई सूचियों को अधिक पसंद करता हूं क्योंकि वे गतिशील रूप से विकसित और सिकुड़ सकते हैं।


6
वैक्टर (= मूल रूप से सरणियाँ) वह भी कर सकते हैं और उनके लिए परिशोधन लागत आमतौर पर स्थानीयता-संदर्भ संदर्भों के कारण सूचियों की तुलना में छोटी होती है।
कोनराड रुडोल्फ

7

कोई भी कभी भी अपनी खुद की लिंक्ड सूची को कोड नहीं करता है। वह मूर्खतापूर्ण होगा। लिंक की गई सूची का उपयोग करने का आधार यह कोड अधिक गलत है।

इन दिनों, लिंक की गई सूची बनाना छात्रों के लिए एक अभ्यास है, ताकि वे अवधारणा को समझ सकें। इसके बजाय, हर कोई पूर्व-निर्मित सूची का उपयोग करता है। C ++ में, हमारे प्रश्न के विवरण के आधार पर, इसका मतलब शायद एक stl वेक्टर ( #include <vector>) होगा।

इसलिए, एक लिंक बनाम एक सरणी को चुनना पूरी तरह से आपके ऐप की जरूरतों के सापेक्ष प्रत्येक संरचना की विभिन्न विशेषताओं को तौलना है। अतिरिक्त प्रोग्रामिंग बोझ पर काबू पाने से निर्णय पर शून्य प्रभाव होना चाहिए।


2
Er..umm .. std :: वेक्टर एक सरणी है, लिंक-लिस्ट नहीं है। मानक लिंक्ड-लिस्ट है, ठीक है, std :: लिस्ट।
जेम्स कुर्रान

1
हाँ, लेकिन मुझे लगता है कि वेक्टर एक करीब है जो एक गतिशील सरणी प्रतिस्थापन के लिए पूछ रहा है।
जोएल कोएहॉर्न 14

@Joel, मैं केवल इस प्रश्न को संबंधित करने की कोशिश कर रहा था क्योंकि यह मेरे साथ इस साथी द्वारा किया गया था जो C ++ सीखने की कोशिश कर रहा था। मैं अपनी खुद की लिंक्ड सूची या तो कोडिंग से परेशान नहीं होता, लेकिन इस तरह उसने मुझसे पूछा। :-)
ओनोरियो कैटेनियास

स्मृति-विवश वातावरण (माइक्रोकंट्रोलर) में जिसके लिए कस्टम कंपाइलर हैं, न कि सभी भाषा (जैसे, C ++ में कंटेनर) को लागू किया जाता है। तो यह हो सकता है कि आपको अपनी खुद की लिंक्ड सूची को कोड करना होगा। nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus
मिन्ह ट्रान

6

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


6

Arrays समझ में आता है कि वस्तुओं की सही संख्या कहाँ ज्ञात होगी, और कहाँ सूचकांक द्वारा खोज समझ में आता है। उदाहरण के लिए, यदि मैं बिना किसी संपीड़न के अपने वीडियो आउटपुट की सटीक स्थिति को स्टोर करना चाहता था, तो मैं संभवतः आकार की एक सरणी का उपयोग करूँगा [1024] [768]। यह मुझे वही प्रदान करेगा जो मुझे चाहिए, और दी गई पिक्सेल का मूल्य प्राप्त करने के लिए एक सूची बहुत, बहुत धीमी होगी। उन जगहों पर जहां एक सरणी का कोई मतलब नहीं है, आमतौर पर डेटा से प्रभावी ढंग से निपटने के लिए एक सूची की तुलना में बेहतर डेटा प्रकार हैं।


6

लिंक बनाम लिंक की गई सूची:

  1. खंडित स्मृति के कारण कभी-कभी मेमोरी आवंटन विफल हो जाएगा।
  2. Arrays में कैशिंग बेहतर है क्योंकि सभी तत्वों को सन्निहित स्मृति स्थान आवंटित किया जाता है।
  3. अरोड की तुलना में कोडिंग अधिक जटिल है।
  4. Arrays के विपरीत लिंक्ड सूची पर कोई आकार की बाधा नहीं
  5. लिंक्ड लिस्ट में इंसर्शन / डिलीटेशन तेज़ है और ऐरे में एक्सेस तेज़ है।
  6. मल्टी-थ्रेडिंग दृष्टिकोण से बेहतर लिस्टेड लिंक।

-1: इन सभी को प्रमाणित करने की आवश्यकता है, न कि केवल गणना करने की।
जॉन सॉन्डर्स

उपरोक्त बिंदुओं में प्रत्येक बिंदु को पहले ही समझाया जा चुका है। लेटकोमर होने के नाते मेरे पास एनुमरेट करने के अलावा कोई दूसरा विकल्प नहीं था। BTW, कौन सा आप को समझाया जाएगा?
AKS

अगर उन्हें पहले ही समझाया जा चुका है, तो आप क्यों जवाब दे रहे हैं?
जॉन सॉन्डर्स

2
ताकि यह आपको चर्चा का संक्षिप्त रूप दे। और मुझे इस तरह के उत्तर पसंद हैं ताकि मुझे बार-बार एक ही स्पष्टीकरण न पढ़ना पड़े। और मैंने इसे उन लोगों के लिए किया, जिनकी सोच की शैली मेरी है। अलग-अलग ppl के अलग-अलग स्टाइल होते हैं। कुछ नया नहीं।
AKS

3

चूंकि सरणियाँ प्रकृति में स्थिर हैं, इसलिए मेमोरी आवंटन जैसे सभी ऑपरेशन केवल संकलन के समय होते हैं। इसलिए प्रोसेसर को अपने रनटाइम पर कम प्रयास करना पड़ता है।


3

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

पहले हमें ध्यान देना चाहिए कि यदि आप सेट के बाहर की वस्तुओं के संदर्भों को बनाए रखना चाहते हैं, तो आप संभवतः ऑब्जेक्ट्स को स्टोर करने के बजाय सरणी में स्टोरिंग पॉइंटर्स को समाप्त कर देंगे। अन्यथा आप सरणी में सम्मिलित नहीं कर पाएंगे - यदि ऑब्जेक्ट सरणी में एम्बेड किए गए हैं तो वे सम्मिलन के दौरान स्थानांतरित हो जाएंगे और उनके लिए कोई भी संकेत अमान्य हो जाएगा। सरणी अनुक्रमित के लिए भी यही सत्य है।

आपकी पहली समस्या, जैसा कि आपने स्वयं नोट किया है, सम्मिलन है - लिंक की गई सूची ओ (1) में सम्मिलित करने की अनुमति देती है, लेकिन एक सरणी को आमतौर पर ओ (एन) की आवश्यकता होगी। इस समस्या को आंशिक रूप से दूर किया जा सकता है - डेटा संरचना तैयार करना संभव है जो सरणी-जैसे-ऑर्डिनल एक्सेस इंटरफ़ेस देता है जहां पढ़ना और लिखना दोनों सबसे खराब, लघुगणक हैं।

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


क्या आप इसे विस्तृत रूप से बता सकते हैं: "यह एक डेटा संरचना बनाना संभव है जो सरणी-जैसे-ऑर्डिनल एक्सेस इंटरफ़ेस देता है जहां पढ़ना और लिखना दोनों सबसे खराब, लघुगणक हैं।"
हेंगामेह

1
डायनामिक एरे / वेरिएंट सेक्शन के तहत विकिपीडिया पर कुछ सामान है। यह काफी नहीं है जो मेरे मन में था, हालांकि ... कल्पना करें कि बी + पेड़ की तरह संरचना है जिसमें पृष्ठों के साथ कोई कुंजी नहीं है, इसके बजाय प्रत्येक मध्यवर्ती पृष्ठ को याद है कि उप-पृष्ठों में से प्रत्येक में कितने तत्व हैं, जबकि पत्ती पृष्ठ बस पकड़ते हैं एक छोटे से सरणी में तत्व। जब एक पत्ता पृष्ठ में एक तत्व सम्मिलित करते हैं, तो आपको कमरा बनाने के लिए ~ आधा पृष्ठ स्थानांतरित करना होगा, फिर ऊपर जाएं और सभी पूर्वज पृष्ठों पर आइटम गणना को अपडेट करें। जब कोई तत्व #N देख रहा हो, तो केवल तब तक अधीनस्थ पृष्ठ आइटम गणना जोड़ें जब तक कि आप N को पार नहीं कर लेते, और फिर उस सबट्री में उतरते हैं
DenNukem

3

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

- बड़ा सवाल यह है कि क्या हम दोनों का हाइब्रिड हो सकता है। क्या अजगर और पर्ल सूची के रूप में लागू कुछ।


3

लिंक्ड सूची

इसके अधिक बेहतर जब यह सम्मिलन के बारे में आता है! मूल रूप से क्या करता है कि यह सूचक के साथ व्यवहार करता है

1 -> 3 -> 4

डालें (2)

१ ........ ३ ...... ४
..... २

आखिरकार

1 -> 2 -> 3 -> 4

3 पर 2 बिंदुओं में से एक तीर और 2 पर 1 अंक का तीर

सरल!

लेकिन ऐरे से

| 1 | 3 | 4 |

डालें (2) | 1 | 3 | | 4 | | 1 | | 3 | 4 | | 1 | 2 | 3 | 4 |

वैसे अंतर की कल्पना कोई भी कर सकता है! सिर्फ 4 इंडेक्स के लिए हम 3 चरणों का प्रदर्शन कर रहे हैं

यदि सरणी की लंबाई एक मिलियन है तो क्या होगा? क्या सरणी कुशल है? जवाब न है! :)

यही बात डिलीट करने के लिए जाती है! लिंक्ड लिस्ट में हम केवल पॉइंटर का उपयोग कर सकते हैं और एलिमेंट क्लास में एलीमेंट और नेक्स्ट को शून्य कर सकते हैं! लेकिन सरणी के लिए, हमें ShiftLeft () करने की आवश्यकता है

उम्मीद है की वो मदद करदे! :)


3

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

मान लीजिए कि आप डेटा के साथ कई चीजों को स्टोर करना चाहते हैं, तो उन्हें आसानी से लिंक की गई सूची में बढ़ाया जा सकता है।

एसटीएल कंटेनरों में आमतौर पर दृश्य के पीछे सूची कार्यान्वयन जुड़ा होता है।


3

1- लिंक्ड सूची एक गतिशील डेटा संरचना है, इसलिए यह मेमोरी को आवंटित और डील करके रनटाइम पर बढ़ और सिकुड़ सकती है। इसलिए लिंक की गई सूची का प्रारंभिक आकार देने की कोई आवश्यकता नहीं है। नोड्स का सम्मिलन और विलोपन वास्तव में आसान है।

2- लिंक्ड लिस्ट का साइज़ रन टाइम पर बढ़ या घट सकता है, इसलिए कोई मेमोरी अपव्यय नहीं होता है। सरणी के मामले में, कई मेमोरी अपव्यय है, जैसे अगर हम आकार 10 की एक सरणी घोषित करते हैं और इसमें केवल 6 तत्वों को संग्रहीत करते हैं तो 4 तत्वों का स्थान बर्बाद हो जाता है। लिंक की गई सूची में ऐसी कोई समस्या नहीं है क्योंकि मेमोरी केवल आवश्यकता होने पर आवंटित की जाती है।

3- डेटा संरचनाएं जैसे कि स्टैक और क्वीन्स को लिंक्ड लिस्ट का उपयोग करके आसानी से लागू किया जा सकता है।


2

लिंक की गई सूची का उपयोग करने का एकमात्र कारण यह है कि तत्व सम्मिलित करना आसान है (हटाना भी)।

Disadvatige हो सकता है कि पॉइंटर्स बहुत जगह लें।

और उस कोडिंग के बारे में कठिन है: आमतौर पर आपको एसटीएल में कोड लिंक्ड सूची (या केवल एक बार) की आवश्यकता नहीं होती है और यदि आप अभी भी इसे करना चाहते हैं तो यह इतना जटिल नहीं है।


2
पॉइंटर्स बहुत जगह लेते हैं? ज़रुरी नहीं। यदि आप बूलियन्स की एक लिंक की गई सूची को संग्रहीत कर रहे हैं, तो निश्चित रूप से, प्रतिशत बुद्धिमान बिंदु बहुत अधिक स्थान लेते हैं। लेकिन अगर आप जटिल वस्तुओं (जो आमतौर पर मामला है) का भंडारण कर रहे हैं, तो संकेत शायद नगण्य होंगे।
Herms

मुस्कुराहट भूल गए :) लेकिन कहा 'नहीं' कर सकता है '।
1915 बजे user15453

1

मुझे यह भी लगता है कि लिंक सूची सरणियों से अधिक बेहतर है। क्योंकि हम लिंक सूची में अनुरेखण करते हैं, लेकिन सरणियों में नहीं


1

आपकी भाषा के आधार पर, इन नुकसानों और फायदों पर विचार किया जा सकता है:

C प्रोग्रामिंग लैंग्वेज : जब एक लिंक्ड लिस्ट (आमतौर पर स्ट्रक्चर पॉइंटर्स के माध्यम से) का उपयोग किया जाता है, तो विशेष रूप से यह सुनिश्चित करना चाहिए कि आप मेमोरी को लीक नहीं कर रहे हैं। जैसा कि पहले उल्लेख किया गया था, लिंक की गई सूचियों में फेरबदल करना आसान है, क्योंकि सभी कर रहे थे बदलते संकेत, लेकिन क्या हम सब कुछ मुक्त करने के लिए याद करने जा रहे हैं?

जावा : जावा में एक स्वचालित कचरा इकट्ठा होता है, इसलिए मेमोरी को लीक करना एक मुद्दा नहीं होगा, लेकिन उच्च स्तर के प्रोग्रामर से छिपा हुआ एक लिंक की गई सूची का कार्यान्वयन विवरण है। सूची के बीच से एक नोड को हटाने जैसे तरीके एक प्रक्रिया से अधिक जटिल हैं, क्योंकि भाषा के कुछ उपयोगकर्ता इसे होने की उम्मीद करेंगे।


1

किसी सरणी पर लिंक की गई सूची क्यों? खैर जैसा कि कुछ ने पहले ही कहा है, सम्मिलन और विलोपन की अधिक गति।

लेकिन शायद हमें या तो सीमा के साथ नहीं रहना है, और एक ही समय में दोनों का सर्वोत्तम प्राप्त करना है ... एह?

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

यदि आपके पास वास्तव में बड़ा सरणी है, तो आप इसे दूसरे, बहुत छोटे सरणी या लिंक की गई सूची के साथ जोड़ सकते हैं, जहां छोटे वाले के पास 20, 50, 100 सबसे हाल ही में उपयोग किए गए आइटम हैं। यदि आवश्यक नहीं है तो छोटी लिंक की गई सूची या सरणी में, आप बड़े सरणी में जाते हैं। यदि वहां पाया जाता है, तो आप इसे अनुमान से छोटी लिंक की गई सूची / सरणी में जोड़ सकते हैं कि 'हाल ही में उपयोग की जाने वाली चीजें सबसे अधिक फिर से उपयोग की जाने वाली हैं' (और हां, संभवतः सूची से हाल ही में उपयोग किए गए आइटम को टकराते हुए)। जो कई मामलों में सच है और एक समस्या को हल किया है जिसमें मुझे .ASP सुरक्षा अनुमतियों की जाँच करने में आसानी, लालित्य और प्रभावशाली गति के साथ मॉड्यूल की जाँच करनी थी।


1

जबकि आप में से कई लोगों ने प्रमुख सूची से जुड़ा हुआ है। लिंक की सूची बनाम सरणी से, अधिकांश तुलनाएं यह बताई हैं कि एक दूसरे से बेहतर / बदतर कैसे है। आप सरणी में रैंडम एक्सेस कर सकते हैं लेकिन लिंक की गई सूची और अन्य में संभव नहीं है। हालाँकि, यह मान रहा है कि लिंक सूचियाँ और सरणी एक समान अनुप्रयोग में लागू होने जा रहे हैं। हालाँकि एक सही उत्तर यह होना चाहिए कि किसी विशेष एप्लिकेशन परिनियोजन में लिंक सूची को सरणी और इसके विपरीत कैसे पसंद किया जाएगा। मान लीजिए आप एक डिक्शनरी एप्लिकेशन को लागू करना चाहते हैं, तो आप क्या उपयोग करेंगे? Array: mmm यह द्विआधारी खोज और अन्य खोज एल्गो के माध्यम से आसान पुनर्प्राप्ति की अनुमति देगा .. लेकिन आपको लगता है कि लिंक सूची बेहतर कैसे हो सकती है। क्या आप शब्दकोश में "बूँद" खोजना चाहते हैं। क्या ए-> बी-> सी-> डी ----> की एक लिंक सूची होना समझ में आता है

A -> B -> C -> ...Z
|    |    |
|    |    [Cat, Cave]
|    [Banana, Blob]
[Adam, Apple]

अब ऊपर का दृष्टिकोण बेहतर है या [एडम, एप्पल, केला, ब्लॉब, कैट, केव] का एक सपाट सरणी? क्या यह सरणी के साथ भी संभव होगा? तो लिंक सूची का एक बड़ा फायदा यह है कि आप एक तत्व को न केवल अगले तत्व की ओर इशारा कर सकते हैं, बल्कि कुछ अन्य लिंक सूची / सरणी / ढेर / या किसी अन्य मेमोरी लोकेशन पर भी रख सकते हैं। Array एक फ्लैट सन्निहित मेमोरी है जिसे उस स्टोर के आकार में ब्लॉक किया गया है, जो स्टोर करने जा रहा है .. दूसरी तरफ लिंक लिस्ट नॉन-कंटेग्यूस मेमोरी यूनिट्स का एक हिस्सा है (कुछ भी हो सकता है और कुछ भी स्टोर कर सकता है) और प्रत्येक की ओर इशारा करते हुए जिस तरह से आप चाहते हैं। इसी तरह से आप USB ड्राइव बना रहे हैं। अब आप फ़ाइलों को किसी भी सरणी या लिंक सूची के रूप में सहेजना चाहेंगे? मुझे लगता है कि आपको यह विचार मिलता है कि मैं क्या इंगित कर रहा हूं :)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.