2009-04-04 19 views
21

सी # में गोलाकार रूप से जुड़ी सूची बनाने का सबसे अच्छा तरीका क्या होगा। क्या मुझे इसे LinkedList < टी> संग्रह से प्राप्त करना चाहिए? मैं अपने संपर्कों को स्टोर करने के लिए इस लिंक्ड लिस्ट का उपयोग करके एक सरल पता पुस्तिका बनाने की योजना बना रहा हूं (यह एक चूसने वाला वाई पता पुस्तिका होगा, लेकिन मुझे कोई परवाह नहीं है क्योंकि मैं इसका उपयोग करने वाला अकेला हूं)। मैं मुख्य रूप से केवल महत्वपूर्ण रूप से जुड़ी सूची बनाना चाहता हूं ताकि मैं इसे अन्य परियोजनाओं में फिर से उपयोग कर सकूं।सी # में एक गोलाकार रूप से जुड़ी सूची बनाना?

यदि आपको नहीं लगता कि लिंक्ड लिस्ट जाने का सही तरीका है तो मुझे बताएं कि कौन सा तरीका बेहतर होगा।

उत्तर

74

इन उत्तरों से ज्यादातर वास्तव में सवाल है, केवल इरादा के पदार्थ में नहीं मिलता है के रूप में, शायद यह मदद मिलेगी:

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

static class CircularLinkedList { 
    public static LinkedListNode<T> NextOrFirst<T>(this LinkedListNode<T> current) 
    { 
     return current.Next ?? current.List.First; 
    } 

    public static LinkedListNode<T> PreviousOrLast<T>(this LinkedListNode<T> current) 
    { 
     return current.Previous ?? current.List.Last; 
    } 
} 

अब तुम सिर्फ myNode.NextOrFirst() myNode के बजाय फोन कर सकते हैं।अगला और आपके पास गोलाकार लिंक्ड सूची का सभी व्यवहार होगा। आप अभी भी निरंतर समय निकासी कर सकते हैं और सूची में सभी नोड्स के पहले और बाद में डालें। यदि सर्कुलर लिंक्ड सूची का कोई अन्य महत्वपूर्ण हिस्सा है तो मुझे याद आ रही है, मुझे बताएं।

+8

यह सिर्फ सही आदमी है, धन्यवाद! बेहतर शैली के लिए, कोई '??' का उपयोग कर सकता है ऑपरेटर: वर्तमान वापसी। अगला ?? current.List.First; – Julien

+1

@ जुलिएन भाषा की जटिलताएं पठनीयता की सहायता नहीं करती हैं। –

+2

एक बात जो यहां ध्यान देने योग्य है वह यह है कि 'वर्तमान। सूची' संभावित रूप से शून्य हो सकती है यदि नोड स्वयं अनलिंक हो। Https://msdn.microsoft.com/en-us/library/h339c45b(v=vs.110).aspx देखें –

4

मुझे नहीं लगता कि एक परिपत्र लिंक्ड सूची संपर्क सूची के लिए सही डेटा संरचना है। एक साधारण सूची <> या संग्रह <> पर्याप्त होना चाहिए।

6

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

आप शायद अपना खुद का लेखन बंद कर सकते हैं।

4

क्या आपके पास गोलाकार रूप से जुड़ी सूची (यानी होमवर्क) का उपयोग करने के लिए एक विशिष्ट आवश्यकता है? यदि नहीं, तो मैं आपके संपर्कों को संग्रहीत करने के लिए सरल List<T> कक्षा का उपयोग करने का सुझाव दूंगा।

3

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

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


मुझे नहीं लगता कि एक लिंक की गई सूची गोलाकार बफर (मूल प्रश्न) के लिए जाने का सबसे प्रभावी तरीका है।

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

+0

'एरे जो उन्हें बहुत तेज बनाता है और उनकी प्रकृति से गतिशील आकार बदलने की आवश्यकता नहीं होती है' - आप ऐसा क्यों कहते हैं? – nawfal

+0

वह सबसे अधिक संभावना कहता है कि यदि आप एक परिपत्र सूची का उपयोग कर रहे हैं, तो संभवतः आपके पास एक सेट क्षमता है और इसके आगे गतिशील रूप से आकार बदलने की आवश्यकता नहीं है। – bgura

0

मुझे लगता है कि इस समस्या के लिए सबसे सही डेटा संरचना एक परिपत्र दोगुनी लिंक्ड सूची है। इस डेटा संरचना के साथ आप स्वतंत्र रूप से ऊपर और नीचे संपर्क सूची के माध्यम से

3
class CircularArray<T> : IEnumerator<T> 
{ 
    private readonly T[] array; 
    private int index = -1; 
    public T Current { get; private set; } 

    public CircularArray(T[] array) 
    { 
     Current = default(T); 
     this.array = array; 
    } 

    object IEnumerator.Current 
    { 
     get { return Current; } 
    } 

    public bool MoveNext() 
    { 
     if (++index >= array.Length) 
      index = 0; 
     Current = array[index]; 
     return true; 
    } 

    public void Reset() 
    { 
     index = -1; 
    } 

    public void Dispose() { } 
} 
0
class Program 
{ 
    static void Main(string[] args) 
    { 
     int[] numbers = { 1, 2, 3, 4, 5, 6, 7 }; 

     IEnumerable<int> circularNumbers = numbers.AsCircular(); 

     IEnumerable<int> firstFourNumbers = circularNumbers.Take(4); // 1 2 3 4 
     IEnumerable<int> nextSevenNumbersfromfourth = circularNumbers 
      .Skip(4).Take(7); // 4 5 6 7 1 2 3 
    } 
} 

public static class CircularEnumerable 
{ 
    public static IEnumerable<T> AsCircular<T>(this IEnumerable<T> source) 
    { 
     if (source == null) 
      yield break; // be a gentleman 

     IEnumerator<T> enumerator = source.GetEnumerator(); 

     iterateAllAndBackToStart: 
     while (enumerator.MoveNext()) 
      yield return enumerator.Current; 

     enumerator.Reset(); 
     if(!enumerator.MoveNext()) 
      yield break; 
     else 
      yield return enumerator.Current; 
goto iterateAllAndBackToStart; 
    } 
} 

आप आगे जाना चाहते हैं, तो एक CircularList बनाने के लिए और जब अपने नमूने में की तरह घूर्णन Skip() छोड़ ही प्रगणक पकड़ कर सकते हैं।

2

एक मॉड्यूलस आधारित समाधान।

परिपत्र बफर एक कच्चे सरणी (या यह महत्वपूर्ण कार्यों के लिए संग्रह के किसी भी अन्य प्रकार)

T[] array; 

के रूप में कार्यान्वित किया जाता है और हम int current_index में वर्तमान आइटम के सूचकांक संग्रहीत करते हैं, हम कर सकते हैं चक्र ऊपर और निम्नानुसार बफर नीचे:

T NextOrFirst() 
{ 
    return array[(current_index + 1) % array.Length]; 
} 

T PreviousOrLast() 
{ 
    return array[(current_index + array.Length - 1) % array.Length]; 
} 

उसी दृष्टिकोण का उपयोग किसी भी XAML बाइंडिंग संग्रह के साथ किया जा सकता है।

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