SortedList <>, SortedDictionary <> और शब्दकोश <>


98

मुझे लगता है कि SortedList<TKey, TValue> SortedDictionary<TKey, TValue>और Dictionary<TKey, TValue>एक ही इंटरफेस को लागू करने के लिए।

  1. जब हम के लिए चुनते चाहिए SortedListऔर SortedDictionaryअधिक Dictionary?
  2. आवेदन के संदर्भ में SortedListऔर क्या अंतर है SortedDictionary?

जवाबों:


101
  1. जब दोनों में से किसी एक पर तत्वों की पुनरावृति होती है, तो तत्वों को क्रमबद्ध किया जाएगा। इसके साथ ऐसा नहीं है Dictionary<T,V>

  2. MSDN के बीच अंतर के पते SortedList<T,V>और SortedDictionary<T,V>:

सॉर्टेड्डर (TKey, TValue) जेनेरिक क्लास O (लॉग एन) पुनर्प्राप्ति के साथ एक द्विआधारी खोज पेड़ है , जहां n शब्दकोश में तत्वों की संख्या है। इस संबंध में, यह SortedList (TKey, TValue) सामान्य वर्ग के समान है। दो वर्गों में समान ऑब्जेक्ट मॉडल हैं, और दोनों में ओ (लॉग एन) पुनर्प्राप्ति है। जहाँ दो वर्ग अलग-अलग होते हैं, वे स्मृति उपयोग और सम्मिलन और गति की गति में होते हैं:

SortedList (TKey, TValue) SortedDictionary (TKey, TValue) की तुलना में कम स्मृति का उपयोग करता है।

सॉर्टेडवार्डर (TKey, TValue) में अनट्रेस डेटा के लिए तेजी से प्रविष्टि और निष्कासन कार्य हैं: SortedList (TKey, TValue) के लिए O (n) के विपरीत O (log n)।

यदि सूची को छांटे गए डेटा से एक ही बार में पॉपुलेट किया जाता है, तो SortedList (TKey, TValue) SortedDictionary (TKey, TValue) की तुलना में तेज है।


21
एक और व्यावहारिक अंतर, कि SortedListआप सूचकांक द्वारा पुनः प्राप्त कर सकते हैं (जैसा कि कुंजी द्वारा पुनर्प्राप्ति का विरोध किया गया है) और SortedDictionaryआप नहीं कर सकते।
एंड्रयू सविनाख

65

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

मैं शब्दकोशों में अंतर बताता हूँ।

ऊपर की तस्वीर से पता चलता है कि एनालॉग की Dictionary<K,V>तुलना में हर मामले में समान या तेज है Sorted, लेकिन अगर तत्वों के आदेश की आवश्यकता होती है, जैसे उन्हें मुद्रित करने के लिए, Sortedकिसी को चुना जाता है।

Src: http://people.cs.aau.dk/~normark/oop-csharp/html/notes/collections-note-time-complexity-dmail.html


1
बहुत बढ़िया अवलोकन। हालांकि मूल प्रश्न में नहीं, यह ध्यान दिया जाना चाहिए कि यदि आप Immutableइन शब्दकोशों के संस्करणों के बीच चयन करते हैं , कि Sortedसंस्करण अक्सर गैर-सॉर्ट किए गए समकक्षों की तुलना में लगभग 40-50% तेजी से होते हैं (फिर भी O(log(n)), लेकिन प्रति ऑरेक्युलर रूप से तेजी से) । हालांकि इनपुट कितने प्रकार का है, इसके आधार पर समय अलग-अलग हो सकता है। Stackoverflow.com/a/30638592/111575
हाबिल

21

एक प्रदर्शन परीक्षण के परिणामों को संक्षेप में प्रस्तुत करने के लिए - SortedList बनाम SortedDictionary बनाम शब्दकोश बनाम हैशटेबल , विभिन्न परिदृश्यों के लिए सबसे अच्छा से सबसे खराब परिणाम:

स्मृति उपयोग:

SortedList<T,T>
Hashtable
SortedDictionary<T,T>
Dictionary<T,T>

निवेशन:

Dictionary<T,T>
Hashtable
SortedDictionary<T,T>
SortedList<T,T>

खोज संचालन:

Hashtable
Dictionary<T,T>
SortedList<T,T>
SortedDictionary<T,T>

लूप ऑपरेशन

SortedList<T,T>
Dictionary<T,T>
Hashtable
SortedDictionary<T,T>

1
जब इन परीक्षा परिणामों की जांच करते हैं, तो कोई SortedDictionary के raison d'etre पर सवाल उठा सकता है ।
बीवर

1
यदि आपकी Collectionजरूरत है sortedतो आप के बारे में भूल सकते हैं Hashtableऔर Dictionary: यदि आप अपने संग्रह को एक शॉट में आबाद करते हैं -> SortedList के लिए जाते हैं, लेकिन यदि आप आशा करते हैं कि आपको अक्सर .Addऔर .Removeआइटम की आवश्यकता होगी -> SortedDictionary के लिए जाना।
अमा

शायद sortedइसका मतलब स्पष्ट करने की आवश्यकता है: जब आप आइटमों को For Each MyItem in Collectionमूल रूप से .Addसंपादित करने के क्रम में संसाधित होने के बजाय करते हैं, तो sorted Collectionउन्हें Keyमानों (मानों में परिभाषित IComparer) पर मानदंड के लिए एक ऑर्डर रिकॉर्डिंग में संसाधित करेंगे । उदाहरण के लिए, यदि आपकी कुंजी स्ट्रिंग है, तो आपके संग्रह को डिफ़ॉल्ट रूप से आपकी कुंजी के वर्णानुक्रम के अनुसार संसाधित किया जाएगा, लेकिन आप हमेशा एक कस्टम छँटाई नियम को परिभाषित कर सकते हैं।
अमा

9
  1. जब आप चाहते हैं कि संग्रह कुंजी द्वारा सॉर्ट किया जाए जब आप उस पर पुनरावृति करते हैं। यदि आपको अपने डेटा को क्रमबद्ध करने की आवश्यकता नहीं है, तो आप सिर्फ एक शब्दकोश के साथ बेहतर हैं, इसका प्रदर्शन बेहतर होगा।

  2. SortedList और SortedDictionary बहुत ज्यादा एक ही काम करते हैं, लेकिन अलग तरीके से लागू किया जाता है, इस प्रकार अलग अलग ताकत और कमजोरियों यहाँ समझाया गया है


8

मैं प्रस्तावित उत्तर प्रदर्शन पर ध्यान केंद्रित कर देख सकता हूं। नीचे दिया गया लेख प्रदर्शन के संबंध में कुछ भी नया प्रदान नहीं करता है, लेकिन यह अंतर्निहित तंत्र की व्याख्या करता है। यह भी ध्यान दें कि यह Collectionप्रश्न में वर्णित तीन प्रकारों पर ध्यान केंद्रित नहीं करता है , लेकिन सभी प्रकार के System.Collections.Genericनामस्थानों को संबोधित करता है।

http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx

अर्क:

शब्दकोश <>

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

SortedDictionary <>

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

SortedList <>

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


अंतर्निहित प्रक्रियाओं का टेंटेटिव सारांश

प्रतिक्रिया बहुत स्वागत है क्योंकि मुझे यकीन है कि मुझे सब कुछ ठीक नहीं मिला।

  • सभी सरणियाँ आकार की हैं n
  • गैर-सॉर्ट किया गया सरणी = .Add / .Remove O (1) है, लेकिन .Item (i) O (n) है।
  • सॉर्ट किया गया सरणी = .Add / .Remove O (n) है, लेकिन .Item (i) O (लॉग एन) है।

शब्दकोश

स्मृति

KeyArray(n) -> non-sorted array<pointer>
ItemArray(n) -> non-sorted array<pointer>
HashArray(n) -> sorted array<hashvalue>

जोड़ना

  1. HashArray(n) = Key.GetHash# O (1) जोड़ें
  2. KeyArray(n) = PointerToKey# O (1) जोड़ें
  3. ItemArray(n) = PointerToItem# O (1) जोड़ें

हटाना

  1. For i = 0 to n, iजहां HashArray(i) = Key.GetHash # O (लॉग एन) (सॉर्ट किया गया सरणी) खोजें
  2. HashArray(i)# O (n) (सॉर्ट किया गया सरणी) निकालें
  3. KeyArray(i)# O (1) निकालें
  4. ItemArray(i)# O (1) निकालें

वस्तु ले आओ

  1. For i = 0 to n, iजहां HashArray(i) = Key.GetHash# O (लॉग एन) (सॉर्ट किया गया सरणी) खोजें
  2. वापसी ItemArray(i)

फन्दा बनाना

  1. For i = 0 to n, वापसी ItemArray(i)

SortedDictionary

स्मृति

KeyArray(n) = non-sorted array<pointer>
ItemArray(n) = non-sorted array<pointer>
OrderArray(n) = sorted array<pointer>

जोड़ना

  1. KeyArray(n) = PointerToKey# O (1) जोड़ें
  2. ItemArray(n) = PointerToItem# O (1) जोड़ें
  3. For i = 0 to n, iजहां KeyArray(i-1) < Key < KeyArray(i)( ICompare#) का उपयोग करके खोजें
  4. जोड़े OrderArray(i) = n# हे (एन) (क्रमबद्ध सरणी)

हटाना

  1. For i = 0 to n, iजहां KeyArray(i).GetHash = Key.GetHash# O (n) खोजें
  2. KeyArray(SortArray(i))# O (n) निकालें
  3. ItemArray(SortArray(i))# O (n) निकालें
  4. OrderArray(i)# O (n) (सॉर्ट किया गया सरणी) निकालें

वस्तु ले आओ

  1. For i = 0 to n, iजहां KeyArray(i).GetHash = Key.GetHash# O (n) खोजें
  2. वापसी ItemArray(i)

फन्दा बनाना

  1. For i = 0 to n, वापसी ItemArray(OrderArray(i))

SortedList

स्मृति

KeyArray(n) = sorted array<pointer>
ItemArray(n) = sorted array<pointer>

जोड़ना

  1. For i = 0 to n, iजहां KeyArray(i-1) < Key < KeyArray(i)( ICompare#) का उपयोग करके खोजें (लॉग एन)
  2. KeyArray(i) = PointerToKey# O (n) जोड़ें
  3. ItemArray(i) = PointerToItem# O (n) जोड़ें

हटाना

  1. For i = 0 to n, iजहां KeyArray(i).GetHash = Key.GetHash# O (लॉग एन) खोजें
  2. KeyArray(i)# O (n) निकालें
  3. ItemArray(i)# O (n) निकालें

वस्तु ले आओ

  1. For i = 0 to n, iजहां KeyArray(i).GetHash = Key.GetHash# O (लॉग एन) खोजें
  2. वापसी ItemArray(i)

फन्दा बनाना

  1. For i = 0 to n, वापसी ItemArray(i)

0

@Lev द्वारा प्रस्तुत प्रत्येक मामले में एक प्रदर्शन स्कोर प्रदान करने की कोशिश करते हुए, मैंने निम्नलिखित मूल्यों का उपयोग किया:

  • ओ (१) = ३
  • ओ (लॉग एन) = 2
  • ओ (n) = 1
  • O (1) या O (n) = 2
  • O (लॉग एन) या O (n) = 1.5

परिणाम (उच्च = बेहतर) हैं:

Dictionary:       12.0 
SortedDictionary:  9.0 
SortedList:        6.5

बेशक, प्रत्येक उपयोग-केस कुछ निश्चित कार्यों को अधिक वजन देगा।


1
अंगूठे के एक नियम के रूप में, O (n) का वजन होगा लॉग (n) / log (2) (+1 प्रत्येक बार n डबल्स), जबकि O (n) का वजन n होगा। तो आपका वेटिंग 4 के आकार के लिए सही होगा। इससे आगे की कोई भी चीज आपके 2: 1 के अनुपात को जल्दी देख लेगी। उदाहरण के लिए यदि n = 100 है, तो आपके पास O (लॉग एन) = 15. होना चाहिए एक अनुकरणीय सोच के बाद, आपका O (1) वजन 100 होगा। निष्कर्ष: O (n) लड़ाई को बहुत जल्दी खो देता है। यदि ऐसा नहीं होता है, तो इसका मतलब है कि आपका सरणी छोटा है, और फिर दक्षता चिंता का विषय नहीं है।
अमा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.