सम्मिलित करें, हटाएं और MostFrequent का समर्थन करने वाली एक कुशल डेटा संरचना


14

मान लें कि हम एक सेट है D और के प्रत्येक सदस्य एक डेटा और कुंजी युग्म है। हम एक डेटा संरचना चाहते हैं जो निम्नलिखित कार्यों का समर्थन करेगी:D

  • सम्मिलित करें में ,डी(d,k)D
  • सदस्य हटाएं , ( खोजने के लिए खोज करने की आवश्यकता नहीं है , उदाहरण के लिए में एक सदस्य को अंक ),डी डीeeeD
  • MostFrequent है, जो एक सदस्य रिटर्न eD ऐसी है कि De.key में सबसे अधिक बार होने वाली चाबियों में से एक है (ध्यान दें कि सबसे लगातार कुंजी को विशिष्ट होने की आवश्यकता नहीं है)।D

इस डेटा संरचना का एक कुशल कार्यान्वयन क्या होगा?

मेरा समाधान कुंजियों और उनके आवृत्तियों के लिए एक ढेर है, जो आवृत्तियों के साथ-साथ एक हैश तालिका है, जहां हैश फ़ंक्शन समान तालिका में एक ही स्लॉट के लिए एक ही कुंजी के साथ सदस्यों को मैप करता है (प्रत्येक भाग से दूसरे भाग तक)।

यह दे सकते हैं Θ(lgn) पहले दो कार्यों के लिए और तीसरे के लिए (सबसे खराब स्थिति के समय)।Θ(1)

मैं सोच रहा हूं कि क्या अधिक कुशल समाधान है? (या एक ही दक्षता के साथ एक सरल समाधान?)


आप चाहें तो हैश टेबल के बजाय एक साधारण संतुलित बाइनरी सर्च ट्री का उपयोग कर सकते हैं।
जो

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

@ जो, हैश टेबल के स्थान पर BST का उपयोग करने से MostFrequent संचालन कम कुशल हो जाएगा, लेकिन यह स्मृति के लिए एक उचित व्यापार बंद हो सकता है।
केवह

2
यदि केवल तुलना का उपयोग कर रहे हैं, तो कम से कम एक डालें / MostFrequent को तत्व भिन्नता समस्या के लिए कम सीमा के कारण परिशोधन करना होगा । Ω(logn)
आर्यभट्ट

1
स्ट्रीमिंग मॉडल में कुछ दिलचस्प संरचनाएं भी हैं। स्प्रिंगरलिंक.com
जो

जवाबों:


7

गणना के तुलना-आधारित मॉडल में, आप एक साधारण ढेर के बजाय एक फिबोनाची ढेर का उपयोग करके प्राथमिकता कतार को लागू कर सकते हैं। यह आपको निम्नलिखित सीमाएं देगा: डालने के लिए amortized समय और हटाए गए कार्यों के लिए O ( log n ) amortized समय।O(1)O(logn)

यदि आप तुलना-आधारित मॉडल से प्रस्थान करते हैं और रैम मॉडल को अपनाते हैं जहां कुंजियों को बाइनरी स्ट्रिंग्स के रूप में माना जाता है, प्रत्येक एक या एक से अधिक मशीन शब्दों में निहित है, तो आप अपनी प्राथमिकता कतार को में लागू कर सकते हैं । दरअसल, आप दोनों डालने और हटाने के संचालन के लिए प्राप्त कर सकते हैं हे ( o(logn)औरहे(1)findMin ऑपरेशन के लिए समय। थोरुप ने यह साबित कर दियाO(loglogn)O(1)

यदि हम एस ( एन ) प्रति कुंजी समय में सॉर्ट कर सकते हैं , तो हम एस ( एन ) समय में निरंतरता और अपडेट (डालने और हटाने) में एक प्राथमिकता कतार को लागू कर सकते हैं ।nS(n)S(n)

एम। थोरुप को देखें। प्राथमिकता कतार और छँटाई के बीच समानता, 2002. प्रोक में। FOCS 2002

जब से हम प्रकार में कर सकते हैं अपेक्षित समय और रैखिक स्थान, जैसा कि दिखाया गया हैO(nloglogn)

वाई। हान और एम। थोरुप। में छँटाई पूर्णांक अपेक्षित समय और रैखिक स्थान। प्रोक में। FOCS 2002O(nloglogn)

बद्ध सिद्ध होता है।


1

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

नीचे दिया गया मेरा समाधान वास्तव में सिर्फ एक "अक्षम" प्राथमिकता कतार के साथ आपका समाधान है जो इस मामले के लिए अच्छी तरह से काम करता है: कुंजी की बाल्टी की दोहरी लिंक की गई सूचियों के रूप में लागू की गई अधिकतम प्राथमिकता कतार में O (1) इन्सर्टिन, डिलीटमैक्स, रिमूफ़ ब्रॉकेट और increaseKey।


बकेट्स की एक डबल-लिंक की गई सूची को बनाए रखें, जहां प्रत्येक बकेट में गैर-खाली हैश सेट ऑफ़ कीज़ (कि मैं एक कॉहोर्ट कहूँगा) और एक पॉज़िटिव पूर्णांक (जिसे मैं वेलकाउंट कहूँगा)। एक बाल्टी बी में, बी के कोहोर्ट में प्रत्येक कुंजी k में आपके द्वारा बनाए गए सेट में इसके साथ जुड़े अद्वितीय मानों की संख्या समान है। उदाहरण के लिए, यदि आपके सेट में जोड़े (ए, सेब), (ए, एवोकैडो), (बी, केला), (सी, ककड़ी), (डी, ड्रैगन फ्रूट) हैं, जहां एकल अक्षर कुंजी और फल हैं मान, तो आपके पास दो बकेट होंगे: एक बकेट में 2 की वैलकाउंट होगी और एक कोहर्ट में केवल एक की होगी: a। अन्य बकेट में 1 की वालकाउंट होगी और एक कोहार्ट में तीन चाबियां बी, सी और डी होंगी।

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

बकेट लिस्ट के अलावा, हमें एक SetMap की आवश्यकता होगी, जो कि ValueBuckets के लिए हैश मैप मैपिंग कुंजी है। एक ValueBucket एक जोड़ी है जिसमें ValueSet (मानों का एक गैर-खाली हैश सेट) और एक बाल्टी के लिए एक गैर-शून्य सूचक होता है। एक कुंजी कश्मीर के साथ जुड़े ValueSet में कश्मीर से जुड़े सभी अद्वितीय मूल्य हैं। एक ValueSet से जुड़े बकेट पॉइंटर में एक Valuehet के आकार के बराबर एक कोहोर्ट है। सेटटेप में एक कुंजी k के साथ जुड़ा हुआ बकेट भी BucketList में कुंजी k के साथ जुड़ा हुआ है।

C ++ में:

struct Bucket {
    unsigned ValCount;
    unordered_set<Key> Cohort;
    Bucket * heavier;
    Bucket * lighter;
};
Bucket * BucketListHead;
Bucket * BucketListTail;

struct ValueBucket {
  unordered_set<Value> ValueSet;
  Bucket * bucket;
};
unordered_map<Key, ValueBucket> SetMap;

एक अधिकतम-आवृत्ति की-वैल्यू जोड़ी को खोजने के लिए, हमें बस बकेट लिस्ट के प्रमुख को देखने की जरूरत है, कोहोर्ट में एक कुंजी ढूंढें, सेटपेज़ में उस कुंजी को देखें, और उसके वैल्यूबकेट के ValueSet में एक मान ढूंढें। (ओफ़्फ़!)

कुंजी-मूल्य जोड़े को सम्मिलित करना और हटाना मुश्किल है।

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


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

यहां मेरे समाधान के बारे में सोचने का एक और तरीका है: यह वास्तव में "अक्षम" प्राथमिकता कतार के साथ सिर्फ आपका समाधान है जो इस मामले के लिए अच्छी तरह से काम करता है। कुंजियों के बकेट की दोहरी लिंक की गई सूचियों के रूप में कार्यान्वित एक अधिकतम प्राथमिकता कतार में O (1) इन्सर्टिन, डिलीटमैक्स, रिमूवफ्रॉमबकेट और वृद्धिकाइ है।
jbapple

ValueBuckets के लिए कुंजियों से मानचित्रण बनाए रखने के लिए सबसे प्रभावी तरीका (सबसे खराब स्थिति में) संभवतः एक खोज ट्री है।
राफेल

राफेल - मुझे यकीन नहीं है कि तुम क्या कर रहे हो। क्या आप कह रहे हैं कि हैश टेबल व्यवहार में महंगे हैं, या सबसे खराब स्थिति में उनका प्रदर्शन खराब है, या कोई तीसरी बात है?
जप्‍पल

-3

सबसे खराब स्थिति

सम्मिलित करें : O(1)

ढूँढें-मिनट : O(1)

कमी-कुंजी : O(1)

O(loglogn)

O(n)

प्रमाण

[0,N) हे(एलजी एलजी मैंn{n,एन}) समय।

जिसे निम्नलिखित के संयोजन के साथ स्थापित किया गया है:

LEMMA 3. Let τ(n,N) be the delete time for a priority queue for up to n integers in the range [0,N) supporting insert and dec-key in constant time. Then τ(n,N)τ(N,N). This holds whether τ is amortized or worst-case.

and:

THEOREM 6. Theorem 6. We can implement a priority queue that with n integer keys in the range [0,N) in linear space supporting find-min, insert, and dec-key in constant time, and delete in O(1+log log nlog log q) time for a key of rank q.

Reference

Thorup, Mikkel. “Integer Priority Queues with Decrease Key in Constant Time and the Single Source Shortest Paths Problem.” In Proceedings of the Thirty-fifth Annual ACM Symposium on Theory of Computing, 149–158. STOC ’03. New York, NY, USA: ACM, 2003.


ध्यान दें कि सभी प्राथमिकता वाली कतारों में 'get-min' और 'extract-min' का समर्थन करने वाले स्ट्रक्चर में 'get-max' और 'extract-max' का समर्थन करने वाले स्ट्रक्चर में जाना तुच्छ है।
एटी

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