लगातार परिशोधन समय


जवाबों:


776

सरल समय में समझाया गया समय:

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

तो इससे कोई फर्क नहीं पड़ता कि ऑपरेशन एक समय में एक बार बहुत धीमा है, जब तक कि "एक बार में एक बार" धीमेपन के लिए काफी हद तक पतला हो। अनिवार्य रूप से परिशोधन समय का अर्थ है "यदि आप कई ऑपरेशन करते हैं, तो प्रति ऑपरेशन औसत समय लगता है"। अमूर्त समय स्थिर होना जरूरी नहीं है; आपके पास रैखिक और लघुगणक परिशोधन समय या जो कुछ भी हो सकता है।

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

तो हर बार जब आप बड़े होते हैं, तो आप अंतिम विस्तार के रूप में लगभग दो बार लेते हैं। लेकिन आप भी इसे करने से पहले दो बार इंतजार कर चुके हैं! प्रत्येक इज़ाफ़ा की लागत इस प्रकार सम्मिलन के बीच "फैल सकती है"। इसका मतलब यह है कि दीर्घकालिक में, एम आइटम को सरणी में जोड़ने के लिए लिया गया कुल समय है O(m), और इसलिए परिशोधन समय (यानी प्रति प्रविष्टि समय) है O(1)


61
नोटेशन के संदर्भ में बस एक नोट: O (n) का एक परिशोधित निरंतर निष्पादन समय अक्सर O (n) + के रूप में O (n) + के रूप में लिखा जाता है। प्लस चिन्ह का जोड़ दर्शाता है कि निष्पादन समय ओ (एन) होने की गारंटी नहीं है और वास्तव में उस निष्पादन समय से अधिक हो सकता है।
जेफपोर्स

1
अंतरिक्ष आवंटित करने के मामले में, क्या यह ढेर से है?
committedandroider

3
मैं "आप वास्तव में सबसे बुरे मामले की परवाह नहीं करते हैं" से असहमत हैं। यह उपयोग के मामले पर निर्भर करता है। यदि अंत में, आप केवल 1 मिलियन ऑपरेशन के उद्धरण के परिणाम में रुचि रखते हैं, तो आप वास्तव में परवाह नहीं करते हैं। लेकिन अगर यह एक वास्तविक समय ऐप है, जो लगातार डेटा पढ़ रहा है और फिर इसका जवाब दे रहा है, तो आपको एक बड़ी समस्या हो सकती है, अगर उस डेटा को संसाधित करने में हर 1 मिलियन डेटा आइटम संसाधित होने के बाद सामान्य से 1 मिलियन गुना अधिक समय लगता है!
काई पेट्ज़के

2
@Jeffpowrs मुझे लगा कि O (n) रैखिक समय था और O (1) निरंतर समय था । तो क्या इसका मतलब है कि O (1) + को निरंतर समय दिया जाएगा और O (n) + को रैखिक समय में परिशोधन किया जाएगा ?
जॉन मेयर

1
@ जॉनमन यस।
आर्टिलियस

55

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

यह महत्वपूर्ण है कि एल्गोरिथ्म गारंटी देता है कि संचालन के अनुक्रम के बाद महंगे संचालन को परिशोधन किया जाएगा और जिससे पूरे ऑपरेशन ओ (1) का प्रतिपादन होगा।

या अधिक सख्त शब्दों में,

एक निरंतर सी है, जैसे कि परिचालन के प्रत्येक अनुक्रम के लिए (एक महंगा ऑपरेशन के साथ भी समाप्त होता है) लंबाई एल, समय सी * एल से अधिक नहीं है (धन्यवाद राफेल डाउगर्ड )


11
"बड़ी मात्रा में परिचालनों के बाद" - लगातार परिशोधित समय को इस स्थिति की आवश्यकता नहीं है। एक निरंतर सी है, जैसे कि प्रत्येक क्रम के संचालन के लिए (यह भी एक महंगा ऑपरेशन के साथ समाप्त होता है) लंबाई एल, समय सी * एल से अधिक नहीं है।
राफेल डोवगर्ड

यह कहां से आ रही राशि का दोगुना आवंटन है? क्या हमें एक प्रविष्टि के लिए आवंटित नहीं करना चाहिए? या यह एक काल्पनिक उदाहरण है?
१५

@talekeDskobaDa यह एक मनमाना उदाहरण नहीं है, बल्कि एक व्यापक रूप से उपयोग किया जाने वाला एल्गोरिदम है। यदि हम आपके सुझाव के अनुसार एक समय में एक प्रविष्टि के लिए स्थान आवंटित करते हैं, तो एकल मान डालने के लिए परिमित समय O (n) होगा। यदि हम पूर्ण होने पर अंतरिक्ष को दोगुना कर देते हैं, तो परिशोधित समय बहुत बेहतर है, ओ (1)। स्पष्ट होने के लिए, एक समय में एक आइटम के लिए जगह आवंटित करने के साथ समस्या यह है कि एक सरणी को निरंतर स्थान के एक बड़े ब्लॉक की आवश्यकता होती है। ओएस से एक बड़ा ब्लॉक प्राप्त करना आसान है लेकिन मौजूदा ब्लॉक का विस्तार करना अक्सर असंभव होता है क्योंकि इसके बाद सीधे कुछ अन्य डेटा संग्रहीत हो सकते हैं।
आर्टिलियस

23

इसके बारे में एक सहज ज्ञान युक्त तरीका विकसित करने के लिए, गतिशील सरणी में तत्वों के सम्मिलन पर विचार करें (उदाहरण के लिए std::vectorC ++)। चलो एक ग्राफ तैयार करते हैं, जो सरणी में एन तत्वों को सम्मिलित करने के लिए आवश्यक संचालन (वाई) की संख्या की निर्भरता दिखाता है:

भूखंड

ब्लैक ग्राफ के वर्टिकल हिस्से एक सरणी का विस्तार करने के लिए मेमोरी के reallocations से मेल खाते हैं। यहाँ हम देख सकते हैं कि इस निर्भरता को एक रेखा के रूप में दर्शाया जा सकता है। और यह रेखा समीकरण Y=C*N + b( हमारे मामले में Cस्थिर, b= 0 है)। इसलिए हम कह सकते हैं कि हमें C*Nएन तत्वों को सरणी में जोड़ने के लिए औसतन संचालन करने की आवश्यकता है, या C*1एक तत्व जोड़ने के लिए ऑपरेशन (निरंतर समय में परिशोधन)।


14

मैं विकिपीडिया स्पष्टीकरण के नीचे उपयोगी पाया, 3 बार पढ़ने के बाद:

स्रोत: https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_Array

“डायनामिक एरे

डायनामिक एरे के लिए पुश ऑपरेशन का परिशोधित विश्लेषण

एक गतिशील सरणी पर विचार करें जो आकार में बढ़ता है क्योंकि इसमें अधिक तत्व जोड़े जाते हैं जैसे कि जावा में एक ArrayList। यदि हमने आकार 4 के एक गतिशील सरणी के साथ शुरुआत की, तो उस पर चार तत्वों को धकेलने के लिए निरंतर समय लगेगा। फिर भी पाँचवें तत्व को उस सरणी पर धकेलने में अधिक समय लगेगा क्योंकि सरणी को वर्तमान आकार (8) के दोहरे आकार का एक नया सरणी बनाना होगा, पुराने तत्वों को नए सरणी पर कॉपी करना होगा और फिर नए तत्व को जोड़ना होगा। अगले तीन पुश ऑपरेशन इसी तरह लगातार समय लेते हैं, और फिर बाद में इसके अतिरिक्त सरणी आकार की एक और धीमी गति से दोहरीकरण की आवश्यकता होगी।

सामान्य तौर पर अगर हम मनमाने ढंग से संख्या n को आकार n की एक सरणी पर विचार करते हैं, तो हम ध्यान देते हैं कि पुश संचालन में निरंतर समय लगता है सिवाय पिछले एक को छोड़कर जो आकार को दोगुना करने के लिए O (n) समय लेता है। चूंकि कुल एन ऑपरेशन थे इसलिए हम इसका औसत निकाल सकते हैं और पा सकते हैं कि डायनामिक ऐरे पर तत्वों को आगे बढ़ाने के लिए: O (n / n) = O (1), निरंतर समय। "

एक साधारण कहानी के रूप में मेरी समझ के लिए:

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

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

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

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

छोटे कमरे में भी एन 1 मिलियन की तरह बड़ा है, एन (1 मिलियन) की तुलना में 2 ऑपरेशन वास्तव में एक तुलनीय संख्या नहीं है, इसलिए इसे निरंतर या ओ (1) माना जाता है।

यह मानते हुए कि जब हम उपरोक्त सभी को एक और बड़े कमरे में करते हैं, और फिर से स्थानांतरित करने की आवश्यकता होती है। यह अभी भी वैसा ही है। कहते हैं, N2 (कहते हैं, 1 अरब) बड़े कमरे में पैसे की गिनती की नई राशि है

इसलिए, हमारे पास N2 है (जिसमें पिछले से N शामिल है क्योंकि हम छोटे से बड़े कमरे में जाते हैं)

हमें अभी भी केवल 2 ऑपरेशनों की आवश्यकता है, एक को बड़े कमरे में डाला जाता है, फिर एक और बड़े कमरे में स्थानांतरित करने के लिए एक और चाल ऑपरेशन।

तो, एन 2 (1 बिलियन) के लिए भी, यह प्रत्येक के लिए 2 ऑपरेशन है। जो फिर से कुछ भी नहीं है। तो, यह स्थिर है, या O (1)

इसलिए, जैसा कि एन से एन 2 तक बढ़ जाता है, या अन्य, यह ज्यादा मायने नहीं रखता है। यह अभी भी स्थिर है, या N के प्रत्येक के लिए O (1) संचालन आवश्यक है।


अब मान लीजिए, आपके पास 1 के रूप में एन है, बहुत छोटा है, पैसे की गिनती छोटी है, और आपके पास बहुत छोटा कमरा है, जो केवल 1 गिनती के पैसे में फिट होगा।

जैसे ही आप कमरे में पैसे भरते हैं, कमरा भर जाता है।

जब आप बड़े कमरे में जाते हैं, तो मान लें कि इसमें केवल एक और पैसा फिट हो सकता है, कुल 2 पैसे। इसका मतलब है, पिछले स्थानांतरित पैसे और 1 और। और फिर से भर जाता है।

इस तरह, N धीरे-धीरे बढ़ रहा है, और यह कोई अधिक स्थिर O (1) नहीं है, क्योंकि हम पिछले कमरे से सभी पैसे ले जा रहे हैं, लेकिन केवल 1 और पैसा ही फिट कर सकते हैं।

100 बार के बाद, नया कमरा पिछले से 100 पैसे का हिसाब रखता है और 1 और पैसा इसे समायोजित कर सकता है। यह O (N) है, क्योंकि O (N + 1) O (N) है, यानी 100 या 101 की डिग्री समान है, दोनों सैकड़ों हैं, पिछली कहानी के विपरीत, लाखों लोगों के लिए और अरबों के लिए ।

तो, यह हमारे पैसे (चर) के लिए कमरे (या मेमोरी / रैम) आवंटित करने का अक्षम तरीका है।


तो, एक अच्छा तरीका 2 की शक्तियों के साथ, अधिक कमरे आवंटित कर रहा है।

1 कमरे का आकार = फिट 1 पैसा पैसे की गिनती
2 कमरे का आकार = पैसे की 4 गिनती
3 कमरे का आकार फिट बैठता है = पैसे की 8 गिनती
4 वें कमरे का आकार फिट बैठता है = पैसे की 16 गिनती
5 वें कमरे का आकार = फिट बैठता है 32 पैसे के
6 वें कमरे के आकार = फिट बैठता है 64 पैसे के
7 वें कमरे के आकार की गणना = पैसे के 128 गिनती में
8 वें कमरे के आकार में फिट बैठता है = धन की गिनती के लिए
9 वें कमरे के आकार में 256 फिट बैठता है = धन के
10 वें कमरे के आकार में 512 की संख्या
फिट बैठता है
। ..
16 वें कमरे का आकार = 65,536 पैसे की गिनती फिट बैठता है
...
32 वें कमरे का आकार = 4,294,967,296 पैसे का हिसाब
...
64 वें कमरे का आकार = 18,446,744,073,709,551,616 पैसे का हिसाब

यह बेहतर क्यों है? क्योंकि यह हमारी रैम में मेमोरी की मात्रा की तुलना में, शुरुआत में और बाद में तेजी से बढ़ने लगता है।

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

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


2
आह, तो यह ओ (सबसे बुरा मामला / # संचालन का) है। मुझे यह उत्तर सबसे अच्छा लगता है।
न्यूक्लियराइड

1

ऊपर दिए गए स्पष्टीकरण एग्रीगेट एनालिसिस पर लागू होते हैं, कई ऑपरेशनों पर "औसत" लेने का विचार। मुझे यकीन नहीं है कि वे कैसे बैंकर्स-विधि या भौतिकविदों के तरीकों पर लागू होते हैं।

अभी। मैं सही उत्तर के बारे में निश्चित नहीं हूं। लेकिन यह दोनों भौतिकविदों + बैंकर के तरीकों की सिद्धांत स्थिति के साथ करना होगा:

(परिचालनों की लागत का परिमाण)> = (परिचालनों की वास्तविक लागत का योग)।

मुख्य कठिनाई जो मुझे आती है, वह यह है कि परिचालनों की परिशोधित-विषमता-संबंधी लागत सामान्य-विषमता-लागत से भिन्न होती है, मुझे यकीन नहीं है कि परिशोधन-लागत के महत्व को कैसे रेट किया जाए।

यही कारण है कि जब कोई मेरी परिशोधित-लागत देता है, तो मुझे पता है कि इसकी सामान्य-विषमता की लागत समान नहीं है, तो फिर मैं परिशोधन-लागत से क्या निष्कर्ष निकाल सकता हूं?

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

उदाहरण के लिए: एक रिटायर हीप के लिए, ओ (1) होने के लिए सिर्फ घटती-की होने की परिमित लागत को उद्धृत करना अर्थहीन है क्योंकि "हीप की बढ़ती क्षमता में पहले के संचालन द्वारा किए गए काम" से लागत कम होती है।

या

हमारे पास एक और परिकल्पना हो सकती है जो कि परिशोधन-लागतों के बारे में निम्नानुसार है:

  1. मुझे पता है कि महंगा ऑपरेशन MULTIPLE LOW-COST ऑपरेशन से पहले होने वाला है।

  2. विश्लेषण के लिए, मैं कुछ कम लागत वाले ऑपरेशनों को अधिभारित करने जा रहा हूं, जो कि उनकी तरह-असीम-कोस्ट चेंज नहीं हैं।

  3. इन बढ़ी हुई कम-लागत वाली कार्रवाइयों के साथ, मैं यह साबित कर सकता हूं कि एक्सपेंसिव ऑपेरशन के पास कम से कम ASYMPTOTAASST हैं।

  4. इस प्रकार मैंने n संचालन की लागत के ASYMPTOTIC-BOUND में सुधार / कमी की है।

इस प्रकार परिशोधन-लागत विश्लेषण + परिशोधन-लागत सीमाएं अब केवल महंगे संचालन पर लागू होती हैं। सस्ते ऑपरेशनों में उनकी सामान्य-विषमता-लागत के समान विषम-परिशोधन-लागत होती है।


दिलचस्प विचार।
लोनी बेस्ट

0

किसी भी फ़ंक्शन के प्रदर्शन को "उन सभी कॉल के लिए लिए गए कुल समय" में "फ़ंक्शन कॉल की कुल संख्या" को विभाजित करके औसत किया जा सकता है। यहां तक ​​कि आपके द्वारा किए जाने वाले प्रत्येक कॉल के लिए लंबे समय तक काम करने वाले कार्यों को भी इस तरह से औसत किया जा सकता है।

तो, एक फ़ंक्शन का सार जो प्रदर्शन करता Constant Amortized Timeहै वह यह है कि यह "औसत समय" एक छत तक पहुंचता है जो कि अधिक नहीं होता है क्योंकि कॉल की संख्या में वृद्धि जारी है। किसी विशेष कॉल के प्रदर्शन में भिन्नता हो सकती है, लेकिन लंबे समय तक यह औसत समय बड़ा और बड़ा नहीं होगा।

यह उस चीज का अनिवार्य गुण है जो परफॉर्म करता है Constant Amortized Time

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