2014-05-05 6 views
5

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

यह काम नहीं करता क्या है:

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

ट्रीसेट या हैशसेट में कुशल जोड़ना और हटाना है, लेकिन मैं यह नहीं समझ सकता कि यादृच्छिक वस्तु कैसे प्राप्त करें।

कोई विचार?

सिद्धांत रूप में, एक बी ट्री काम करेगा, अगर मैं खुद को यादृच्छिक लेफ्ट्स या अधिकारों के साथ पेड़ को पार कर सकता हूं, लेकिन मुझे नहीं लगता कि मानक जावा क्लास मुझे यह क्षमता देता है।

यदि मैं मानक जावा कक्षाओं में कुछ भी काम नहीं करता हूं तो मैं किसी तृतीय पक्ष लाइब्रेरी का उपयोग करने के लिए तैयार हूं।

मुझे डुप्लीकेट या नल का समर्थन करने की आवश्यकता नहीं है, न ही इसे थ्रेड सुरक्षित होने की आवश्यकता है।

धन्यवाद।

+0

'ArrayList.remove (int अनुक्रमणिका) 'निरंतर निरंतर समय में चलता है। जहां तक ​​मैं कह सकता हूं, इसका मतलब है कि व्यक्तिगत कॉल रैखिक समय हैं, लेकिन कॉल की श्रृंखला पर औसत समय निरंतर समय तक पहुंचता है। – Aarowaim

+0

उस Aarowaim के लिए धन्यवाद, लेकिन मैं निकालने के लिए वस्तु की अनुक्रमणिका नहीं जानता। मुझे लगता है कि मैं उस जानकारी को हैश मैप या कुछ में अलग से स्टोर कर सकता हूं, लेकिन जैसे ही मैंने ऐरेलिस्ट से ऑब्जेक्ट हटा दिया, सूची में अन्य ऑब्जेक्ट इंडेक्स बदल देंगे, जिसका मतलब है कि हैश मैप में कुछ मान गलत होंगे, और यह मुझे ठीक करने के लिए मुझे रैखिक समय लगेगा। – Magmatic

+0

@ मैग्मैटिक क्या आपको डुप्लिकेट तत्वों की अनुमति देने की आवश्यकता है? – Boann

उत्तर

4

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

class SpecialSet<E> extends AbstractSet<E> implements Set<E> { 
    private final List<E> list = new ArrayList<>(); 
    private final Map<E,Integer> indexMap = new HashMap<>(); 

    @Override 
    public boolean add(E e) { 
     if (contains(e)) return false; 
     indexMap.put(e, list.size()); 
     list.add(e); 
     return true; 
    } 

    @Override 
    public boolean remove(Object o) { 
     Integer indexBoxed = indexMap.remove(o); 
     if (indexBoxed == null) return false; 
     int index = indexBoxed; 
     int last = list.size() - 1; 
     E element = list.remove(last); 
     if (index != last) { 
      indexMap.put(element, index); 
      list.set(index, element); 
     } 
     return true; 
    } 

    public E removeRandom() { 
     E element = list.get((int)(Math.random() * size())); 
     remove(element); 
     return element; 
    } 

    @Override 
    public boolean contains(Object o) { 
     return indexMap.containsKey(o); 
    } 

    @Override 
    public Iterator<E> iterator() { 
     return list.iterator(); 
    } 

    @Override 
    public int size() { 
     return list.size(); 
    } 
} 

क्या वस्तु समानता परीक्षण व्यवहार आप चाहते हैं पर निर्भर करता है, तो आप शायद बाहर HashMap एक IdentityHashMap के लिए एक छोटे से बेहतर करने के लिए स्वैप कर सकता है गति।

+0

वाह, कोड के लिए धन्यवाद! मैंने बस इसे अपनी परियोजना में फेंक दिया। (मैंने केवल "getRandom" को "getRandom" में बदल दिया है और उस पंक्ति को बाहर निकाला है जो इसे हटा देता है)। यह पूरी तरह से काम किया! मैं अक्षम निकालने के साथ एक ArrayList का उपयोग कर रहा था, लेकिन जब मैं इस कोड में बदल गया, प्रसंस्करण का समय 1 9 00 एमएस से 628 एमएस तक गिर गया। वाह वाह वाह! धन्यवाद धन्यवाद धन्यवाद! – Magmatic

+0

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

+0

@AdrianShum की सहायता करेगा, इससे पहले कि आप इसे हटा सकें, आपको तत्व ढूंढना होगा; वह हिस्सा है कि हैश मैप तेजी से बनाता है। – Boann

0

मैं प्रस्ताव करता हूं कि आप एक इंटेजर कुंजी के साथ एक मानचित्र का उपयोग करें। इस तरह आप निकालने के लिए एक यादृच्छिक संख्या उत्पन्न कर सकते हैं।

पाठक के लिए समस्या शेष: बाद में हटाए जाने (या किसी भी ऑपरेशन) पर अंतराल होंगे।

+0

लेकिन यदि आप इसकी कुंजी नहीं जानते हैं तो आप एक मूल्य कैसे हटा सकते हैं? आपको इसे खोजने के लिए अभी भी एक अक्षम रैखिक खोज करने की आवश्यकता होगी। – Magmatic

1

ध्यान दें कि यदि आप आवश्यक अधिकतम आकार को पूर्व-आवंटित करते हैं तो एक साधारण सरणी नौकरी करेगी। "शीर्ष" सूचकांक मान रखें और "शीर्ष" को बढ़ाकर और उस सरणी तत्व में संग्रहीत करके डालें। जब आप हटाते हैं, हटाए गए तत्व में "शीर्ष" मान को नीचे कॉपी करें और "शीर्ष" घटाएं।

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

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