डीईसी और एसटीएल कंटेनरों की सूची में क्या अंतर है?


93

दोनों के बीच क्या अंतर है? मेरा मतलब है कि तरीके समान हैं। तो, एक उपयोगकर्ता के लिए, वे पहचान से काम करते हैं।

क्या वो सही है??


1
मैं पुनरावृति प्रदर्शन में दिलचस्पी रखता हूं .. क्या भीख मांगने से लेकर अंत तक भागने में तेज है?
nkint

जवाबों:


60

(दिनांकित लेकिन अभी भी बहुत उपयोगी) SGI STL सारांश से deque:

एक वेक्टर बहुत अधिक है: वेक्टर की तरह, यह एक अनुक्रम है जो तत्वों के यादृच्छिक अभिगम, निरंतर समय सम्मिलन और अनुक्रम के अंत में तत्वों को हटाने, और रैखिक समय सम्मिलन और बीच में तत्वों को हटाने का समर्थन करता है।

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

यहां listएक ही साइट से सारांश दिया गया है:

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

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


2
std :: सूची में 'ब्याह' विधि भी है जो आपको दो सूचियों को एक साथ मिलाने की अनुमति देता है
रिक

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

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

125

मुझे मतभेदों की सूची दें:

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

  • Deque अंत और शुरुआत दोनों पर फास्ट प्रविष्टि और विलोपन प्रदान करता है। बीच में तत्वों को सम्मिलित करना और हटाना अपेक्षाकृत धीमा है, क्योंकि दोनों सिरों तक के सभी तत्वों को कमरे बनाने या अंतर को भरने के लिए स्थानांतरित किया जा सकता है।
  • में सूची , डालने और तत्वों को हटाने दोनों सिरों सहित प्रत्येक स्थिति, कम से तेज है।

  • Deque : किसी भी प्रविष्टि या समाप्ति के अलावा अन्य तत्वों का विलोपन या विलोपन सभी बिंदुओं, संदर्भों और पुनरावृत्तियों को अमान्य करता है जो कि deque के तत्वों को संदर्भित करता है।
  • सूची : तत्वों को सम्मिलित करना और हटाना अन्य बिंदुओं, संदर्भों और पुनरावृत्तियों को अमान्य नहीं करता है।

जटिलता

             Insert/erase at the beginning       in middle        at the end

Deque:       Amortized constant                  Linear           Amortized constant
List:        Constant                            Constant         Constant

5
@aJ: बीच क्या अंतर है constantऔर amortized constant?
लेज़र

16
लंबी अवधि में ऑपरेशन वर्णित के रूप में व्यवहार करते हैं। हालाँकि, एकल ऑपरेशन निर्दिष्ट से अधिक समय ले सकता है। पूर्व: एक सदिश में एक तत्व डालने के लिए जिसकी वर्तमान क्षमता 10 है और आकार पहले से ही 9 स्थिर है, जहां समय रैखिक है यदि क्षमता 10 है और आकार भी 10. है क्योंकि इसे सभी तत्वों को नई मेमोरी में आवंटित और कॉपी करना है। ।
ए.जे.

5
@ जज: कैसे रेक रैंडम एक्सेस प्रदान करता है? यह संरचना कैसे लागू की गई है?

9

std::list मूल रूप से एक दोहरी लिंक की गई सूची है।

std::dequeदूसरी ओर, अधिक पसंद किया जाता है std::vector । इंडेक्स द्वारा निरंतर पहुंच का समय है, साथ ही शुरुआत और अंत में सम्मिलन और निष्कासन, जो सूची की तुलना में नाटकीय रूप से अलग प्रदर्शन विशेषताओं को प्रदान करता है।


5

एक और महत्वपूर्ण गारंटी यह है कि प्रत्येक अलग-अलग कंटेनर मेमोरी में अपना डेटा स्टोर करता है:

  • एक वेक्टर एक एकल सन्निहित मेमोरी ब्लॉक है।
  • एक लिंक लिंक्ड मेमोरी ब्लॉक का एक सेट है, जहां प्रत्येक मेमोरी ब्लॉक में एक से अधिक तत्व संग्रहीत होते हैं।
  • एक सूची मेमोरी में बिखरे हुए तत्वों का एक सेट है, जिसका अर्थ है: प्रति मेमोरी "ब्लॉक" में केवल एक तत्व संग्रहीत है।

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

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


4

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


2

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


1

यहाँ सूची का एक सबूत-अवधारणा कोड उपयोग है, ओर्ड (1) लुकअप और ओ (1) सटीक LRU रखरखाव देता है। (गैर-मिटाए गए) पुनरावृत्तियों को मिटाए जाने के लिए ऑपरेशन की आवश्यकता है। GPU मेमोरी पर CPU पॉइंटर्स के लिए मनमाने ढंग से बड़े सॉफ्टवेयर प्रबंधित कैश (O) में उपयोग करने की योजना। लिनक्स O (1) शेड्यूलर (LRU <-> रन क्यू प्रति प्रोसेसर) के लिए नोड्स। Unordered_map हैश तालिका के माध्यम से निरंतर समय तक पहुंच है।

#include <iostream> 
#include <list> 
#include <unordered_map>  
using namespace std; 

struct MapEntry {
  list<uint64_t>::iterator LRU_entry;
  uint64_t CpuPtr;
};
typedef unordered_map<uint64_t,MapEntry> Table;
typedef list<uint64_t> FIFO;
FIFO  LRU;        // LRU list at a given priority 
Table DeviceBuffer; // Table of device buffers

void Print(void){
  for (FIFO::iterator l = LRU.begin(); l != LRU.end(); l++) {
    std::cout<< "LRU    entry "<< *l << "   :    " ;
    std::cout<< "Buffer entry "<< DeviceBuffer[*l].CpuPtr <<endl;
  }  
}
int main() 
{ 

  LRU.push_back(0);
  LRU.push_back(1);
  LRU.push_back(2);
  LRU.push_back(3);
  LRU.push_back(4);

  for (FIFO::iterator i = LRU.begin(); i != LRU.end(); i++) {
    MapEntry ME = { i, *i}; 
    DeviceBuffer[*i] = ME;
  }

  std::cout<< "************ Initial set of CpuPtrs" <<endl;
  Print();

  {
    // Suppose evict an entry - find it via "key - memory address uin64_t" and remove from 
    // cache "tag" table AND LRU list with O(1) operations
    uint64_t key=2;
    LRU.erase(DeviceBuffer[2].LRU_entry);
    DeviceBuffer.erase(2);
  }

  std::cout<< "************ Remove item 2 " <<endl;
  Print();

  { 
    // Insert a new allocation in both tag table, and LRU ordering wiith O(1) operations
    uint64_t key=9;
    LRU.push_front(key); 
    MapEntry ME = { LRU.begin(), key };
    DeviceBuffer[key]=ME;
  }

  std::cout<< "************ Add item 9  " <<endl;
  Print();

  std::cout << "Victim "<<LRU.back()<<endl;
} 

क्या आपने इसे सही जगह पर पोस्ट किया है? इस सवाल का जवाब नहीं है।
ब्लास्टफर्न

1

के बीच dequeऔर प्रख्यात मतभेदों के बीचlist

  • के लिए deque:

    वस्तुओं को कंधे से कंधा मिलाकर;

    दो पक्षों (सामने, पीछे) से डेटा जोड़ने के लिए अनुकूलित;

    संख्याओं (पूर्णांक) द्वारा अनुक्रमित तत्व।

    पुनरावृत्तियों द्वारा ब्राउज़ किया जा सकता है और यहां तक ​​कि तत्व के सूचकांक द्वारा भी।

    डेटा तक समय की पहुंच तेज है।

  • के लिये list

    मेमोरी में "बेतरतीब ढंग से" संग्रहीत आइटम;

    केवल पुनरावृत्तियों द्वारा ब्राउज़ किया जा सकता है;

    बीच में सम्मिलन और हटाने के लिए अनुकूलित।

    बहुत खराब स्थानिक इलाके के कारण, डेटा तक समय की पहुंच धीमी है, पुनरावृति के लिए धीमी है।

    बहुत अच्छी तरह से बड़े तत्वों को संभालता है

आप निम्न लिंक की भी जांच कर सकते हैं , जो दो एसटीएल कंटेनरों के बीच प्रदर्शन की तुलना करता है (std :: वेक्टर के साथ)

आशा है कि मैंने कुछ उपयोगी जानकारी साझा की है।

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