क्या कॉन्स्टेंट टाइम और एमोर्नेटेड कॉन्स्टेंट टाइम को प्रभावी रूप से समकक्ष माना जाता है?


16

मुझे एक रैंडम क्यू लिखने की ज़रूरत है जो निरंतरता (ओ (1)) में अपेंडिक्स और यादृच्छिक निष्कासन की अनुमति देता है।

मेरा पहला विचार इसे कुछ प्रकार के एरे के साथ वापस करना था (मैंने एक ArrayList चुना), क्योंकि सरणियों का सूचकांक के माध्यम से निरंतर उपयोग होता है।

हालाँकि, दस्तावेज़ीकरण को देखते हुए, मैंने महसूस किया कि ArrayLists के परिवर्धन को Amortized Constant Time माना जाता है, क्योंकि इसके अतिरिक्त अंतर्निहित सरणी, जो कि O (n) है, के पुनः आरंभ की आवश्यकता हो सकती है।

क्या लगातार स्थिर समय और निरंतर समय प्रभावी रूप से समान हैं, या क्या मुझे कुछ संरचना को देखने की आवश्यकता है जो हर अतिरिक्त पर पूर्ण प्राप्ति की आवश्यकता नहीं है?

मैं यह इसलिए पूछ रहा हूं क्योंकि सरणी आधारित संरचनाएं एक तरफ (जो कि जहां तक ​​मुझे पता है उसके पास हमेशा संकरा समय जोड़ होगा), मैं कुछ भी नहीं सोच सकता जो आवश्यकताओं को पूरा करेगा:

  • कुछ भी पेड़ आधारित सबसे अच्छा हे (लॉग एन) पहुंच पर होगा
  • एक लिंक की गई सूची में संभवतः O (1) जोड़ हो सकते हैं (यदि पूंछ का संदर्भ दिया जाता है), लेकिन एक यादृच्छिक निष्कासन सबसे अच्छा O (n) पर होना चाहिए।

यहाँ पूर्ण प्रश्न है; यदि मैं कुछ महत्वपूर्ण विवरणों से अवगत हुआ:

एक रैंडम क्यू डिजाइन और डिजाइन करें। यह कतार इंटरफ़ेस का एक कार्यान्वयन है जिसमें निष्कासन () ऑपरेशन एक ऐसे तत्व को हटाता है जो कतार में वर्तमान में सभी तत्वों के बीच समान रूप से यादृच्छिक रूप से चुना जाता है। (एक रैंडम क्यू के बारे में सोचें जिसमें हम तत्वों को जोड़ सकते हैं या अंदर तक पहुँच सकते हैं या कुछ यादृच्छिक तत्वों को निकाल सकते हैं।) एक रेंडमक्यू में ऐड (x) और निष्कासन () का संचालन निरंतर समय के अनुसार होना चाहिए।


क्या असाइनमेंट निर्दिष्ट करता है कि यादृच्छिक निष्कासन कैसे किया जाता है? क्या आपको एक कतार तत्व को हटाने या संदर्भ के लिए एक सूचकांक दिया गया है?

यह कोई विवरण नहीं देता है। आवश्यकताएँ केवल एक संरचना है जो कतार इंटरफ़ेस को लागू करती है और इसमें O (1) अतिरिक्त और निष्कासन होते हैं।
कारजेनिकेट

एक तरफ के रूप में - O (n) बढ़ने के साथ एक रहने योग्य सरणी में जरूरी नहीं कि O (1) जोड़ हो: यह इस बात पर निर्भर करता है कि हम सरणी कैसे बढ़ाते हैं। एक निरंतर राशि से बढ़ रही है एक अभी भी हे (एन) है इसके लिए (हम एक है 1/aएक हे (एन) आपरेशन के लिए मौका), लेकिन एक निरंतर पहलू से बढ़ रही a > 1हे (1) इसके अलावा के लिए परिशोधित है: हम एक है (1/a)^nएक हे की संभावना (एन) ऑपरेशन, लेकिन यह संभावना बड़े के लिए शून्य तक पहुंचती है n
जुआन

ArrayLists उत्तरार्द्ध सही का उपयोग करें?
कार्निजेनट

1
प्रश्न के लेखक (मेरे) बार-बार परिशोधन के बारे में सोच रहे थे। मैं अगले संस्करण में स्पष्ट करूँगा। (हालांकि सबसे खराब स्थिति निरंतर समय डी-परिशोधन की तकनीक का उपयोग करके प्राप्त किया जा सकता है ।)
पैट मोरिन

जवाबों:


10

Amortized Constant Time को लगभग हमेशा Constant Time के समतुल्य माना जा सकता है, और आपके आवेदन की बारीकियों को जाने बिना और इस प्रकार का उपयोग आप इस कतार में करने की योजना बना रहे हैं, सबसे अधिक संभावना यह है कि आप कवर किए जाएंगे।

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

हालाँकि, ध्यान रखें कि डिफ़ॉल्ट रूप से, किसी सरणी सूची से यादृच्छिक निष्कासन O (1) नहीं है, यह O (N) है, क्योंकि सरणी सूची हटाए गए स्थान को लेने के लिए हटाए गए आइटम एक स्थिति के बाद सभी आइटमों को स्थानांतरित करते हैं। आइटम। O (1) को प्राप्त करने के लिए आपको सरणी सूची के अंतिम आइटम की प्रतिलिपि के साथ हटाए गए आइटम को बदलने के लिए डिफ़ॉल्ट व्यवहार को ओवरराइड करना होगा, और फिर अंतिम आइटम को हटा दें, ताकि कोई आइटम स्थानांतरित न हो। लेकिन तब, यदि आप ऐसा करते हैं, तो आपके पास अब कोई कतार नहीं है।


1
धिक्कार है, निष्कासन पर अच्छी बात; मैंने ऐसा नहीं माना। और जब से हम बेतरतीब ढंग से तत्वों को हटा रहे हैं, क्या इसका मतलब यह नहीं है कि तकनीकी रूप से यह उस अर्थ में कतार नहीं है?
कैरिजिनेट

हां, इसका मतलब यह है कि आप वास्तव में इसे एक कतार के रूप में नहीं मान रहे हैं। लेकिन मुझे नहीं पता कि आप आइटम निकालने की योजना कैसे बना रहे हैं। यदि उन्हें खोजने का आपका तंत्र उनसे यह उम्मीद करता है कि जिस क्रम में उन्हें जोड़ा गया था, उस कतार में उपस्थित होना है, तो आप भाग्य से बाहर हैं। यदि आपको परवाह नहीं है कि वस्तुओं का क्रम बिगड़ गया है, तो आप ठीक हैं।
माइक नाकिस

2
उम्मीद है कि मेरे RandomQueueलिए Queueइंटरफ़ेस को लागू करना , और आपूर्ति removeविधि के लिए सिर को पॉप करने के बजाय बेतरतीब ढंग से हटाना होगा, इसलिए किसी विशिष्ट आदेश पर भरोसा करने का कोई तरीका नहीं होना चाहिए। मुझे लगता है कि इसके बेतरतीब स्वरूप को देखते हुए, उपयोगकर्ता को यह उम्मीद नहीं करनी चाहिए कि वह कोई विशिष्ट आदेश रखेगा। मैंने स्पष्टीकरण के लिए अपने प्रश्न में असाइनमेंट उद्धृत किया। धन्यवाद।
कारजेनिकेट

2
हां, ऐसा लगता है कि आप ठीक होंगे यदि आप यह सुनिश्चित करते हैं कि आइटम हटाने का तरीका मेरे द्वारा सुझाया गया है।
माइक नाइस

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

14

प्रश्न विशेष रूप से निरंतर समय के लिए पूछता है, और न कि एक परिशोधित स्थिर समय । तो उद्धृत प्रश्न के संबंध में, नहीं, वे प्रभावी रूप से समान नहीं हैं *। हालांकि वे वास्तविक दुनिया अनुप्रयोगों में हैं?

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

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

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

यह इस बात पर भी निर्भर करता है कि वास्तव में यह लागत कितनी अधिक है। वेक्टर्स अच्छा प्रदर्शन करते हैं क्योंकि उनकी वास्तविक लागत अपेक्षाकृत कम है। यदि आप हालांकि हैश मैप पर जाते हैं, तो पुनः प्राप्ति बहुत अधिक हो सकती है। हालांकि फिर से, अधिकांश अनुप्रयोगों के लिए शायद ठीक है, विशेष रूप से लंबे समय तक रहने वाले सर्वर कंटेनर में वस्तुओं पर एक ऊपरी बाध्य है।

* हालांकि यहाँ एक मुद्दा थोड़ा है। किसी भी सामान्य प्रयोजन कंटेनर को डालने के लिए निरंतर समय होना चाहिए दो चीजों में से एक को पकड़ना चाहिए:

  • कंटेनर में एक निश्चित अधिकतम आकार होना चाहिए; या
  • आप मान सकते हैं कि व्यक्तिगत तत्वों का मेमोरी आवंटन निरंतर समय है।

"लीवर सर्वर" यहां उपयोग करने के लिए एक अजीब वाक्यांश है। क्या आपका मतलब "लाइव सर्वर" है?
पीटर जार्जेंस

6

यह निर्भर करता है - क्या आप थ्रूपुट के लिए या विलंबता के लिए अनुकूलन कर रहे हैं:

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

ध्यान दें कि एक प्रणाली में अलग-अलग घटक हो सकते हैं जिन्हें अलग-अलग वर्गीकृत किया जाना चाहिए। उदाहरण के लिए, एक आधुनिक टेक्स्ट प्रोसेसर में एक विलंबता-संवेदनशील UI थ्रेड होगा, लेकिन अन्य कार्यों जैसे कि वर्तनी जाँच या PDF निर्यात के लिए थ्रूपुट-अनुकूलित थ्रेड।

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


दुर्भाग्य से, मेरी पृष्ठभूमि बहुत कम है। यह सवाल समाप्त होता है: "रैंडम क्यू में ऐड (एक्स) और रिमूव () ऑपरेशंस को लगातार ऑपरेशन के अनुसार चलना चाहिए"।
कारजेनिकेट

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

मुझे आभास है कि यह एक प्रोग्रामिंग एक्सरसाइज या टेस्ट हो सकता है। और निश्चित रूप से एक आसान नहीं है। बिल्कुल सच है कि यह बहुत कम ही मायने रखता है।
gnasher729

1

यदि आपसे "amortized स्थिर समय" एल्गोरिथ्म के लिए कहा जाता है, तो आपका एल्गोरिथ्म कभी-कभी एक लंबा समय ले सकता है । उदाहरण के लिए, यदि आप st + :: वेक्टर का C ++ में उपयोग करते हैं, तो इस तरह के वेक्टर में 10 वस्तुओं के लिए स्थान आवंटित हो सकता है, और जब आप 11 वीं वस्तु को आवंटित करते हैं, तो 20 वस्तुओं के लिए स्थान आवंटित किया जाता है, 10 वस्तुओं को कॉपी किया जाता है, और 11 वें को जोड़ा जाता है, जो काफी समय लगता है। लेकिन अगर आप एक लाख ऑब्जेक्ट जोड़ते हैं, तो आपके पास औसत समय होने के साथ 999,980 फास्ट और 20 धीमे संचालन हो सकते हैं।

यदि आपको "निरंतर समय" एल्गोरिथ्म के लिए कहा जाता है, तो आपका एल्गोरिथ्म हमेशा तेज होना चाहिए , हर एक ऑपरेशन के लिए। यह वास्तविक समय प्रणालियों के लिए महत्वपूर्ण होगा जहां आपको एक गारंटी की आवश्यकता हो सकती है कि प्रत्येक एकल ऑपरेशन हमेशा तेज होता है। "लगातार समय" की बहुत आवश्यकता नहीं होती है, लेकिन यह निश्चित रूप से "परिशोधित निरंतर समय" के समान नहीं है।

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