पायथन में स्टैक: परिभाषा, कार्यान्वयन और उदाहरण

आखिरी अपडेट: 02/04/2026
  • पायथन में स्टैक लास्ट-इन, फर्स्ट-आउट मॉडल का पालन करते हैं, जिसमें पुश, पॉप, पीक, साइज और एम्प्टी चेक जैसे मुख्य ऑपरेशन शामिल हैं।
  • पायथन स्टैक को सूचियों, संग्रहों.डेक्यू, क्यू.लाइफोक्यू या कस्टम एकल लिंक सूचियों के साथ कार्यान्वित किया जा सकता है, जिनमें से प्रत्येक के अलग-अलग फायदे और नुकसान हैं।
  • सिंगल-थ्रेडेड कोड के लिए लिस्ट और डेक्यू आदर्श हैं, जबकि मल्टी-थ्रेडेड वातावरण में queue.LifoQueue सबसे सुरक्षित विकल्प है।
  • सही स्टैक इम्प्लीमेंटेशन का चयन प्रदर्शन संबंधी आवश्यकताओं, मेमोरी के व्यवहार और थ्रेड सुरक्षा की आवश्यकता पर निर्भर करता है।

पायथन स्टैक डेटा संरचना

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

इस गाइड में हम विस्तार से जानेंगे कि स्टैक क्या होता है, "लास्ट इन, फर्स्ट आउट" का व्यावहारिक अर्थ क्या है, हर स्टैक को किन-किन ऑपरेशन्स को सपोर्ट करना चाहिए, और लिस्ट, कलेक्शन.डेक्यू, क्यू.लाइफ़क्यू और सिंगली लिंक्ड लिस्ट जैसे विभिन्न टूल्स का उपयोग करके पायथन में स्टैक को कैसे इम्प्लीमेंट किया जाता है।हम परफॉर्मेंस, मेमोरी बिहेवियर, थ्रेड सेफ्टी और वास्तविक दुनिया के उन परिदृश्यों के बारे में भी बात करेंगे जहां स्टैक का उपयोग करना बिल्कुल सही डेटा स्ट्रक्चर है।

पायथन में स्टैक क्या होता है?

स्टैक एक रैखिक डेटा संरचना है जो लास्ट-इन, फर्स्ट-आउट (LIFO) नियम का पालन करती है: स्टैक में डाला गया अंतिम तत्व ही सबसे पहले बाहर आता है।सैद्धांतिक रूप से, आप प्लेटों का ढेर, किताबों का ढेर या कपड़ों का ढेर की कल्पना कर सकते हैं: आप केवल ऊपर से ही वस्तुएं जोड़ या हटा सकते हैं, बीच से या नीचे से नहीं।

इस LIFO व्यवहार का अर्थ है कि जब आप तत्व सम्मिलित (पुश) करते हैं, तो प्रत्येक नया तत्व पिछले तत्वों के ऊपर आ जाता है, और जब आप हटाते (पॉप) हैं, तो आप हमेशा सबसे हाल ही में जोड़ा गया तत्व लेते हैं।आप कभी भी ऊपर के तत्वों को हटाए बिना तीसरे या चौथे तत्व तक पहुंचने के लिए "आगे नहीं बढ़ सकते"।

पायथन में, स्टैक अपने आप में एक अंतर्निहित नामित प्रकार नहीं है; इसके बजाय, हम सूचियों, डेक्यू, LIFO कतारों या कस्टम लिंक्ड सूचियों जैसी मौजूदा डेटा संरचनाओं के ऊपर स्टैक को लागू करते हैं।प्रत्येक विकल्प के प्रदर्शन, मेमोरी उपयोग और थ्रेड सुरक्षा के संदर्भ में अपने-अपने फायदे और नुकसान हैं।

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

कोड में जाने से पहले, एक महत्वपूर्ण विशेषता को ध्यान में रखें: एक अच्छी तरह से कार्यान्वित स्टैक, चाहे उसमें कितने भी तत्व संग्रहीत हों, पुश और पॉप ऑपरेशन को स्थिर समय (O(1) के रूप में दर्शाया जाता है) में निष्पादित करेगा।उस पूर्वानुमानित प्रदर्शन के कारण ही स्टैक का उपयोग एल्गोरिदम और निम्न-स्तरीय प्रणालियों में व्यापक रूप से किया जाता है।

पायथन में स्टैक की अवधारणा

कोर स्टैक संचालन और व्यवहार

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

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

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

अधिकांश स्टैक कार्यान्वयनों में पीक या टॉप ऑपरेशन भी उपलब्ध होते हैं, जो आपको स्टैक से एलिमेंट को हटाए बिना, वर्तमान में सबसे ऊपर मौजूद एलिमेंट को देखने की सुविधा देते हैं।यह उन एल्गोरिदम में विशेष रूप से उपयोगी है जिन्हें अगले मान की जांच करने की आवश्यकता होती है लेकिन फिर भी उसे बाद के लिए वहीं रखना चाहते हैं।

दो अतिरिक्त सहायक ऑपरेशन जो आपको अक्सर देखने को मिलेंगे, वे हैं isempty (या isEmpty) और size, जो यह जांचते हैं कि स्टैक में कोई तत्व है या नहीं और उसमें कितने तत्व हैं।पायथन में, len() बिल्ट-इन फ़ंक्शन और बूलियन चेक दोनों को न्यूनतम कोड के साथ इन हेल्पर्स को लागू करने के लिए आंतरिक रूप से पुन: उपयोग किया जा सकता है।

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

स्टैक का उपयोग कब और क्यों करें

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

इसका एक क्लासिक व्यावहारिक उदाहरण मशीन को खोलना है: आप स्क्रू और पुर्जों को एक निश्चित क्रम में निकालते हैं, और यदि आप इसे सही ढंग से फिर से जोड़ना चाहते हैं, तो आपको उन्हें ठीक विपरीत क्रम में वापस लगाना होगा।इन पुर्जों को स्टैक पर संग्रहित करना उस कार्यप्रवाह के साथ पूरी तरह मेल खाता है।

सॉफ्टवेयर में, स्टैक के सबसे मूलभूत उपयोगों में से एक फंक्शन कॉल स्टैक है: जब भी कोई फंक्शन किसी दूसरे फंक्शन को कॉल करता है, तो पैरामीटर, लोकल वेरिएबल और रिटर्न एड्रेस मेमोरी में स्टैक पर पुश किए जाते हैं।जब कोई फ़ंक्शन रिटर्न करता है, तो उसका फ्रेम पॉप हो जाता है, जिससे कॉलर की स्थिति बहाल हो जाती है।

टेक्स्ट एडिटर, ड्राइंग टूल, आईईडी और कई अन्य एप्लिकेशन में अनडू और रीडू तंत्र आमतौर पर क्रियाओं या स्थितियों के स्टैक पर निर्भर करते हैं।उपयोगकर्ता द्वारा की गई प्रत्येक क्रिया को अनडू स्टैक में डाल दिया जाता है; जब आप Ctrl+Z दबाते हैं, तो एप्लिकेशन सबसे हाल की क्रिया को पॉप करता है और उसे उलट देता है।

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

पायथन सूचियों के साथ स्टैक को लागू करना

पायथन में स्टैक बनाने का सबसे सरल तरीका बिल्ट-इन लिस्ट टाइप का उपयोग करना है, जिसमें append() मेथड का उपयोग करके एलिमेंट को पुश करना और pop() मेथड का उपयोग करके आखिरी एलिमेंट को हटाना शामिल है।सूचियाँ आंतरिक रूप से गतिशील सरणियाँ होती हैं और स्टैक को आवश्यक सभी बुनियादी कार्यक्षमता प्रदान करती हैं।

सूचियों पर आधारित एक न्यूनतम स्टैक, create_stack, push, pop, isempty और show (या top, size, आदि) जैसे सहायक फ़ंक्शन प्रदान कर सकता है, जो आंतरिक रूप से एक साधारण पायथन सूची इंस्टेंस को संसाधित करते हैं।उदाहरण के लिए, create_stack केवल एक खाली सूची लौटा सकता है, और isempty को len(stack) == 0 के रूप में परिभाषित किया जा सकता है।

एक सामान्य पैटर्न यह है कि सूची के अंत को स्टैक के शीर्ष के रूप में माना जाए, इसलिए stack.append(item) एक पुश ऑपरेशन करता है और stack.pop() एक पॉप ऑपरेशन करता है।इससे दोनों ऑपरेशन औसतन स्थिर समय में पूरे होते हैं, और कोड बहुत पठनीय और संक्षिप्त रहता है।

यदि आप अधिक संरचित कोड पसंद करते हैं, तो आप इस व्यवहार को एक कस्टम स्टैक क्लास में रैप कर सकते हैं जो सूची को समाहित करता है और push(), pop(), peek(), is_empty() और size() जैसे स्पष्ट तरीकों को उजागर करता है।एनकैप्सुलेशन से बाद में अतिरिक्त जांच या लॉगिंग के साथ स्टैक का विस्तार करना आसान हो जाता है।

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

हालांकि, एक महत्वपूर्ण बात ध्यान देने योग्य है: सूचियाँ सन्निहित मेमोरी द्वारा समर्थित होती हैं, इसलिए जब वे आरक्षित स्थान से अधिक बढ़ जाती हैं, तो पायथन को एक नया, बड़ा ब्लॉक आवंटित करना पड़ता है और तत्वों को कॉपी करना पड़ता है।अधिकांश समय यह पुनर्वितरण धीरे-धीरे और अदृश्य रूप से होता है, लेकिन कभी-कभी एक सिंगल append() अन्य की तुलना में काफी धीमा हो सकता है।

एक और कमी यह है कि पायथन सूचियाँ एक साथ कई थ्रेड्स द्वारा किए जाने वाले संशोधनों के लिए थ्रेड-सेफ नहीं हैं, जो मल्टी-थ्रेडेड प्रोग्राम में स्टैक का उपयोग करने पर समस्या बन सकती है।ऐसी स्थितियों में, आपको साधारण सूचियों के बजाय queue.LifoQueue जैसे विकल्पों पर विचार करना चाहिए।

collections.deque को स्टैक के रूप में उपयोग करना

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

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

deque का उपयोग करके स्टैक बनाना सीधा है: एक खाली कंटेनर प्राप्त करने के लिए deque() को कॉल करें, फिर push(stack, item) जैसे ऑपरेशन परिभाषित करें जो stack.append(item) को कॉल करते हैं और pop(stack) जो जांचता है कि स्टैक खाली नहीं है और फिर stack.pop() को कॉल करता है।. show(stack) जैसे अतिरिक्त सहायक फ़ंक्शन वर्तमान सामग्री को आसानी से प्रिंट कर सकते हैं।

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

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

queue.LifoQueue के साथ स्टैक को लागू करना

जब थ्रेड सुरक्षा महत्वपूर्ण हो जाती है, तो पायथन में स्टैक को लागू करने के लिए क्यू मॉड्यूल की LifoQueue क्लास सबसे उपयुक्त विकल्प है।लाइफोक्यू मूल रूप से अंतर्निर्मित लॉकिंग तंत्रों के साथ एक थ्रेड-सेफ स्टैक है।

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

LifoQueue स्टैक में एक एलिमेंट जोड़ने के लिए put(item) कमांड का उपयोग किया जाता है, लेकिन अगर स्टैक पहले से ही अपनी अधिकतम क्षमता पर है तो यह कमांड ब्लॉक हो सकता है।एलिमेंट्स को पॉप करने के लिए get() फ़ंक्शन का उपयोग किया जाता है, जो स्टैक खाली होने पर तब तक ब्लॉक हो सकता है जब तक कोई नया आइटम उपलब्ध न हो जाए।

qsize(), full() और empty() जैसे अतिरिक्त सहायक तरीके आपको थ्रेड-सुरक्षित तरीके से स्टैक की वर्तमान स्थिति की जांच करने की अनुमति देते हैं।उदाहरण के लिए, full() आपको बताता है कि क्या और कोई तत्व नहीं जोड़ा जा सकता है, जबकि empty() इंगित करता है कि क्या कुछ भी निकालने के लिए बचा है।

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

यह ध्यान देने योग्य है कि पायथन की थ्रेडिंग का मतलब यह नहीं है कि ग्लोबल इंटरप्रेटर लॉक (GIL) के कारण थ्रेड्स स्वचालित रूप से अलग-अलग CPU कोर पर चलेंगे, लेकिन LifoQueue फिर भी आपके साझा स्टैक को रेस कंडीशन और असंगत स्थिति से सुरक्षित रखता है।कोर में वास्तविक समानांतरता के लिए, आपको मल्टीप्रोसेसिंग या अन्य दृष्टिकोणों की आवश्यकता होगी, फिर भी थ्रेड-सेफ स्टैक की अवधारणा I/O-बाउंड या सहकारी कार्यभार के लिए प्रासंगिक बनी हुई है।

सिंगली लिंक्ड लिस्ट का उपयोग करके स्टैक का कार्यान्वयन

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

आप आमतौर पर वैल्यू और नेक्स्ट रेफरेंस के लिए एट्रिब्यूट्स के साथ एक नोड क्लास को परिभाषित करते हैं, और फिर एक स्टैक क्लास को इम्प्लीमेंट करते हैं जो हेड नोड और साइज काउंटर को ट्रैक करता है।अक्सर, स्टैक खाली होने पर विशिष्ट परिस्थितियों को सरल बनाने के लिए एक डमी हेड नोड का उपयोग किया जाता है।

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

किसी एलिमेंट को पॉप करने के लिए, स्टैक खाली है या नहीं, यह जांचना होता है, फिर उस नोड को लेना होता है जिस पर head.next इंगित करता है, head.next को अगले नोड पर ले जाना होता है, आकार को घटाना होता है और हटाए गए मान को वापस करना होता है।इस ऑपरेशन की समय जटिलता स्थिर है क्योंकि इसमें केवल कुछ ही पॉइंटर अपडेट की आवश्यकता होती है।

इस संरचना के साथ getSize(), isEmpty() और peek() जैसे अतिरिक्त तरीकों को लागू करना आसान है: आकार को एक पूर्णांक के रूप में ट्रैक किया जाता है, isEmpty यह जांच सकता है कि आकार शून्य है या नहीं, और peek स्टैक खाली न होने पर head.next.value लौटाता है।आप सभी स्टैक तत्वों के साथ एक पठनीय स्ट्रिंग उत्पन्न करने के लिए __str__ विधि को भी परिभाषित कर सकते हैं।

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

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

स्टैक के गुण, दक्षता और सीमाएँ

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

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

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

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

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

पायथन स्टैक और थ्रेडिंग संबंधी विचार

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

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

अगर आप बेहद अनुशासित हैं और सावधानीपूर्वक नियंत्रित तरीके से केवल एक ही सिरे से append() और pop() का उपयोग करते हैं, तो Deque अपेक्षाकृत सुरक्षित होते हैं।हालांकि, तब भी, यदि कई थ्रेड बाहरी सिंक्रोनाइज़ेशन के बिना एक ही समय में पढ़ते और लिखते हैं, तो सूक्ष्म समस्याएं और रेस कंडीशन उत्पन्न हो सकती हैं।

मजबूत मल्टी-थ्रेडेड परिदृश्यों के लिए जहां कई थ्रेड एक साथ डेटा पुश और पॉप कर सकते हैं, queue.LifoQueue अनुशंसित स्टैक कार्यान्वयन है।इसके अंतर्निहित लॉक और ब्लॉकिंग सिमेंटिक्स यह सुनिश्चित करते हैं कि समवर्ती एक्सेस स्टैक को दूषित न करे।

इसका नुकसान यह है कि LifoQueue के ऑपरेशन (पुट और गेट) रॉ लिस्ट या डेक्यू मेथड की तुलना में धीमे होते हैं, क्योंकि इसमें थ्रेड्स के बीच अतिरिक्त समन्वय की आवश्यकता होती है।यह अतिरिक्त लागत मायने रखती है या नहीं, यह आपके एप्लिकेशन की प्रदर्शन संबंधी आवश्यकताओं और स्टैक को कितनी बार एक्सेस किया जाता है, इस पर निर्भर करता है।

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

सही पायथन स्टैक कार्यान्वयन का चयन करना

इन सभी विकल्पों को देखते हुए, पायथन में "सर्वश्रेष्ठ" स्टैक कार्यान्वयन आपके संदर्भ पर बहुत हद तक निर्भर करता है: सिंगल-थ्रेडेड बनाम मल्टी-थ्रेडेड, प्रदर्शन संवेदनशीलता, मेमोरी व्यवहार और कोड की स्पष्टता, ये सभी कारक महत्वपूर्ण भूमिका निभाते हैं।ऐसा कोई एक विकल्प नहीं है जो हर परिस्थिति के लिए एकदम सही हो।

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

जब आपके स्टैक का बहुत अधिक उपयोग होगा, जिसमें संभवतः कई तत्व संग्रहीत होंगे, और आप मेमोरी पुनर्आवंटन से संबंधित कम समस्याओं के साथ लगातार तेज़ पुश/पॉप चाहते हैं, तो collections.deque सबसे व्यावहारिक विकल्प होता है।इसका एपीआई सूचियों के समान ही है, इसलिए माइग्रेशन आमतौर पर आसान होता है।

यदि आपको शुरू से ही पता है कि स्टैक को कई थ्रेड्स द्वारा एक्सेस किया जाएगा, खासकर जब पुश और पॉप दोनों एक साथ हो रहे हों, तो queue.LifoQueue सबसे सुरक्षित विकल्प है।यह धीमा हो सकता है, लेकिन यह आपको अपना खुद का लॉकिंग प्रोटोकॉल लागू करने से बचाता है और जटिल रेस स्थितियों से बचने में मदद करता है।

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

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

स्टैक कैसे काम करते हैं, वे किन ऑपरेशनों को सपोर्ट करते हैं, उनके सामान्य पायथन इम्प्लीमेंटेशन और उनके परफॉर्मेंस और थ्रेडिंग ट्रेड-ऑफ को समझकर, आप आत्मविश्वास से उस वर्शन को चुन और इम्प्लीमेंट कर सकते हैं जो आपके प्रोजेक्ट की ज़रूरतों के लिए सबसे उपयुक्त हो, साथ ही ऐसा कोड लिख सकते हैं जो समय के साथ कुशल और समझने में आसान बना रहे।.

मुख्य कोड लिखने के लिए प्रोग्राम का सिद्धांत
संबंधित लेख:
मुख्य कोड लिखने के लिए प्रोग्राम का सिद्धांत
संबंधित पोस्ट: