डेटा संरचना: सामान्य संकल्पना, अंमलबजावणी. सर्वात सोपी डेटा संरचना: रांग, स्टॅक. स्टॅक आणि रिव्हर्स पोलिश नोटेशन वापरणे. msp430 चे उदाहरण वापरून स्टॅक म्हणजे काय आणि त्याची गरज का आहे

इतर मॉडेल 27.06.2019
इतर मॉडेल

आम्ही वाढत्या प्रगत प्रोग्रामिंग भाषा वापरतो ज्या आम्हाला कमी कोड लिहू देतात आणि उत्कृष्ट परिणाम मिळवतात. यासाठी तुम्हाला पैसे द्यावे लागतील. जसजसे आपण कमी-अधिक प्रमाणात कमी-जास्त प्रमाणात व्यवहार करतो, तसतसे आपल्यापैकी अनेकांना स्टॅक आणि हीप म्हणजे काय, संकलन प्रत्यक्षात कसे कार्य करते, स्टॅटिक आणि डायनॅमिक टायपिंगमध्ये काय फरक आहे, इ. मी असे म्हणत नाही की सर्व प्रोग्रामरना या संकल्पना माहित नाहीत - मला असे वाटते की कधीकधी अशा जुन्या-शालेय गोष्टींकडे परत जाणे योग्य आहे.

आज आपण फक्त एका विषयाबद्दल बोलू: स्टॅक आणि हीप. स्टॅक आणि हीप दोन्ही वेगवेगळ्या ठिकाणी संदर्भित करतात जेथे मेमरी व्यवस्थापन होते, परंतु या व्यवस्थापनासाठी धोरण पूर्णपणे भिन्न आहे.

स्टॅक

स्टॅक हे RAM चे क्षेत्र आहे जे प्रत्येक थ्रेडसाठी तयार केले जाते. हे LIFO (लास्ट इन, फर्स्ट आउट) क्रमाने कार्य करते, याचा अर्थ स्टॅकवर ढकललेला मेमरीचा शेवटचा तुकडा स्टॅकमधून पॉप ऑफ होणारा पहिला भाग असेल. प्रत्येक वेळी फंक्शन नवीन व्हेरिएबल घोषित करते तेव्हा ते स्टॅकमध्ये जोडले जाते आणि जेव्हा ते व्हेरिएबल व्याप्तीच्या बाहेर जाते (उदाहरणार्थ, जेव्हा फंक्शन संपते), तेव्हा ते स्टॅकमधून आपोआप काढून टाकले जाते. जेव्हा स्टॅक व्हेरिएबल मुक्त केले जाते, तेव्हा ते मेमरी क्षेत्र इतर स्टॅक व्हेरिएबलसाठी उपलब्ध होते.

स्टॅकच्या या स्वरूपामुळे, CPU वर मेमरी व्यवस्थापन अतिशय तार्किक आणि सोपे आहे; याचा परिणाम उच्च गतीवर होतो, विशेषत: कारण स्टॅक बाइट अपडेट सायकल वेळ खूपच कमी असतो, म्हणजे हा बाइट बहुधा प्रोसेसर कॅशेशी जोडलेला असतो. तथापि, व्यवस्थापनाच्या या कठोर स्वरूपाचे तोटे देखील आहेत. स्टॅकचा आकार एक निश्चित मूल्य आहे आणि स्टॅकवर वाटप केलेली मेमरी मर्यादा ओलांडल्यास स्टॅक ओव्हरफ्लो होईल. प्रवाह तयार केल्यावर आकार सेट केला जातो आणि डेटा प्रकारानुसार प्रत्येक व्हेरिएबलचा कमाल आकार असतो. हे तुम्हाला काही व्हेरिएबल्सचा आकार (जसे की पूर्णांक) मर्यादित करण्यास अनुमती देते आणि तुम्हाला अधिक जटिल डेटा प्रकारांचा आकार (जसे की ॲरे) आधीच घोषित करण्यास भाग पाडते, कारण स्टॅक त्यांना ते बदलू देत नाही. याव्यतिरिक्त, स्टॅकवर स्थित व्हेरिएबल्स नेहमी स्थानिक असतात.

शेवटी, स्टॅक तुम्हाला सर्वात कार्यक्षम पद्धतीने मेमरी व्यवस्थापित करण्यास अनुमती देतो - परंतु जर तुम्हाला डायनॅमिक डेटा स्ट्रक्चर्स किंवा ग्लोबल व्हेरिएबल्स वापरण्याची आवश्यकता असेल, तर तुम्ही हीपकडे पहावे.

ढीग

हीप हे मेमरी स्टोअर आहे, जे RAM मध्ये देखील स्थित आहे, जे डायनॅमिक मेमरी वाटप करण्यास अनुमती देते आणि स्टॅकसारखे कार्य करत नाही: हे फक्त तुमच्या व्हेरिएबल्ससाठी स्टोअरहाऊस आहे. जेव्हा तुम्ही व्हेरिएबल संचयित करण्यासाठी ढीगवर मेमरीचा तुकडा वाटप करता, तेव्हा ते केवळ थ्रेडमध्येच नाही तर संपूर्ण अनुप्रयोगामध्ये प्रवेश करता येते. अशा प्रकारे ग्लोबल व्हेरिएबल्सची व्याख्या केली जाते. जेव्हा अनुप्रयोग समाप्त होतो, तेव्हा सर्व वाटप मेमरी सोडली जाते. जेव्हा ऍप्लिकेशन सुरू होते तेव्हा ढीगाचा आकार सेट केला जातो, परंतु, स्टॅकच्या विपरीत, ते केवळ भौतिकदृष्ट्या मर्यादित असते आणि हे आपल्याला डायनॅमिक व्हेरिएबल्स तयार करण्यास अनुमती देते.

तुम्ही संदर्भांद्वारे ढीगांशी संवाद साधता, ज्याला सामान्यतः पॉइंटर म्हणतात - ही व्हेरिएबल्स आहेत ज्यांची मूल्ये इतर व्हेरिएबल्सचे पत्ते आहेत. जेव्हा तुम्ही पॉइंटर तयार करता, तेव्हा तुम्ही हिपवरील मेमरी स्थानाकडे निर्देश करता, जे व्हेरिएबलचे प्रारंभिक मूल्य सेट करते आणि प्रोग्रामला ते मूल्य कोठे ऍक्सेस करायचे ते सांगते. ढिगाऱ्याच्या गतिशील स्वरूपामुळे, CPU त्याच्या नियंत्रणात भाग घेत नाही; कचरा कलेक्टर (C, C++) नसलेल्या भाषांमध्ये, विकसकाला यापुढे आवश्यक नसलेले मेमरी क्षेत्र मॅन्युअली मुक्त करणे आवश्यक आहे. हे पूर्ण न केल्यास, मेमरी गळती आणि विखंडन होऊ शकते, ज्यामुळे ढीग लक्षणीयरीत्या कमी होईल.

स्टॅकच्या तुलनेत, हीप हळू आहे कारण व्हेरिएबल्स स्टॅकच्या वर बसण्याऐवजी मेमरीमध्ये विखुरलेले असतात. ढीगमध्ये चुकीच्या मेमरी व्यवस्थापनामुळे त्याचे ऑपरेशन मंद होते; तथापि, यामुळे त्याचे महत्त्व कमी होत नाही - जर तुम्हाला डायनॅमिक किंवा ग्लोबल व्हेरिएबल्ससह काम करायचे असेल तर, हीप वापरा.

लास्ट इन - फर्स्ट आउट, "लास्ट इन - फर्स्ट आउट").

बऱ्याचदा, स्टॅकच्या ऑपरेशनच्या तत्त्वाची तुलना प्लेट्सच्या स्टॅकशी केली जाते: वरून दुसरा काढण्यासाठी, आपल्याला वरचा एक काढण्याची आवश्यकता आहे.

काही भाषांमध्ये (उदाहरणार्थ, लिस्प, पायथन), कोणत्याही सूचीला स्टॅक म्हटले जाऊ शकते, कारण त्यांच्यासाठी पॉप आणि पुश ऑपरेशन्स उपलब्ध आहेत. C++ मध्ये, मानक लायब्ररीमध्ये कार्यान्वित रचना आणि पद्धतींचा वर्ग असतो. इ.

विश्वकोशीय YouTube

    1 / 3

    माहितीशास्त्र. डेटा संरचना: स्टॅक. फॉक्सफर्ड ऑनलाइन लर्निंग सेंटर

    #९. स्टॅक / 1. असेंबलर आणि प्रक्रिया / सुरवातीपासून प्रोग्रामिंग

    डेटा नेटवर्कची मूलभूत माहिती. OSI मॉडेल आणि TCP IP प्रोटोकॉल स्टॅक. इथरनेट मूलभूत.

    उपशीर्षके

सॉफ्टवेअर स्टॅक

मेमरी मध्ये संघटना

बऱ्याचदा, स्टॅक एक-मार्गी सूची म्हणून कार्यान्वित केला जातो (यादीतील प्रत्येक घटकामध्ये, स्टॅकमध्ये संग्रहित माहितीव्यतिरिक्त, स्टॅकच्या पुढील घटकाकडे एक सूचक असतो).

परंतु स्टॅक देखील अनेकदा ऑर्डर केलेल्या पत्त्यांसह एका-आयामी ॲरेमध्ये स्थित असतो. ही स्टॅक संस्था सोयीस्कर आहे जर माहिती घटकाने मेमरीमध्ये निश्चित शब्दांची संख्या व्यापली असेल, उदाहरणार्थ, 1 शब्द. हे स्टॅक घटकामध्ये पुढील स्टॅक घटकासाठी स्पष्ट पॉइंटर संचयित करण्याची आवश्यकता दूर करते, जे मेमरी वाचवते. या प्रकरणात, स्टॅक पॉइंटर ( स्टॅक पॉइंटर, - एसपी) हे सहसा प्रोसेसर रजिस्टर असते आणि स्टॅकच्या प्रमुखाच्या पत्त्याकडे निर्देश करते.

उदाहरणार्थ, समजा की स्टॅकचे हेड कमी पत्त्यावर स्थित आहे, खालील घटक वाढत्या पत्त्यावर स्थित आहेत. प्रत्येक वेळी जेव्हा एखादा शब्द स्टॅकवर ढकलला जातो तेव्हा SP प्रथम 1 ने कमी केला जातो आणि नंतर SP कडून पत्ता मेमरीवर लिहिला जातो. प्रत्येक वेळी स्टॅकमधून एखादा शब्द पॉप झाल्यावर, तो प्रथम SP कडील वर्तमान पत्ता वाचतो आणि नंतर SP ची सामग्री 1 ने वाढवतो.

युनिडायरेक्शनल सूची म्हणून स्टॅक आयोजित करताना, स्टॅक व्हेरिएबलचे मूल्य त्याच्या शीर्षस्थानी - शीर्षस्थानी पत्ता दर्शवते. स्टॅक रिक्त असल्यास, पॉइंटर मूल्य NULL आहे.

C मधील स्टॅक अंमलबजावणीचे उदाहरण:

struct स्टॅक (char * डेटा; struct स्टॅक * पुढील; );

स्टॅक ऑपरेशन्स

स्टॅकवर तीन संभाव्य ऑपरेशन्स आहेत: एक घटक जोडणे (उर्फ पुशिंग), घटक (पॉप) काढून टाकणे आणि मुख्य घटक वाचणे (डोकावणे).

ढकलताना (पुश), एक नवीन घटक जोडला जातो, जो पूर्वी डोके होता त्या घटकाकडे निर्देश करतो. नवीन घटक आता प्रमुख घटक बनतो.

घटक (पॉप) हटवताना, पहिला काढून टाकला जातो आणि ज्याला या ऑब्जेक्टचा पॉइंटर (पुढील घटक) होता तो प्रमुख बनतो. या प्रकरणात, काढलेल्या घटकाचे मूल्य परत केले जाते.

शून्य पुश (स्टॅक * पीएस, इंट x) // स्टॅकमध्ये नवीन घटक जोडणे( जर ( ps -> आकार == स्टॅकसाइज ) // स्टॅक ओव्हरफ्लो होत आहे?( fputs ( "त्रुटी: स्टॅक ओव्हरफ्लो \n " , stderr); रद्द करा (); ) इतर ( ps -> आयटम [ ps -> आकार ++ ] = x ; ) ) इंट पॉप ( स्टॅक * पीएस ) // स्टॅकमधून काढा( जर ( ps -> आकार == 0 ) // स्टॅक रिक्त आहे का?( fputs ( "त्रुटी: स्टॅक अंडरफ्लो \ n " , stderr); रद्द करा (); ) बाकी ( परत करा ps -> आयटम [ -- ps -> आकार ]; ) )

अर्जाची व्याप्ती

स्टॅकचे प्रोग्रामिंग दृश्य डेटा स्ट्रक्चर्स, जसे की झाड किंवा आलेख पार करण्यासाठी वापरले जाते. रिकर्सिव फंक्शन्स वापरताना, स्टॅक देखील वापरला जाईल, परंतु हार्डवेअर स्वरूपात. या उद्देशांव्यतिरिक्त, स्टॅकचा वापर आयोजित करण्यासाठी केला जातो

हार्डवेअर व्यत्ययादरम्यान तत्सम प्रक्रिया घडतात (X86 प्रोसेसर हार्डवेअर व्यत्ययादरम्यान स्टॅकवर फ्लॅग रजिस्टर आपोआप सेव्ह करतो). याव्यतिरिक्त, कंपाइलर्स स्टॅकवर प्रक्रिया स्थानिक व्हेरिएबल्स ठेवतात (जर प्रोसेसरला यादृच्छिक स्टॅक स्थानावर प्रवेश असेल).

स्टॅक वापरण्यापूर्वी, ते सुरू केले जाणे आवश्यक आहे जेणेकरून SS:ESP नोंदणी भौतिक रॅमच्या क्षेत्रामध्ये स्टॅकच्या प्रमुखाच्या पत्त्याकडे निर्देश करेल आणि मेमरी सेलची आवश्यक संख्या डेटा संचयित करण्यासाठी राखीव असणे आवश्यक आहे. स्टॅक (स्पष्टपणे, ROM मध्ये स्टॅक, अर्थातच, आयोजित केले जाऊ शकत नाही). ऍप्लिकेशन प्रोग्राम्स, एक नियम म्हणून, ऑपरेटिंग सिस्टमकडून वापरण्यासाठी तयार स्टॅक प्राप्त करतात. संरक्षित प्रोसेसर मोडमध्ये, टास्क स्टेट सेगमेंटमध्ये चार स्टॅक सेगमेंट सिलेक्टर असतात (वेगवेगळ्या विशेषाधिकार स्तरांसाठी), परंतु एका वेळी फक्त एक स्टॅक वापरला जातो.

नमस्कार, मी एका तांत्रिक विद्यापीठात द्वितीय वर्षाचा विद्यार्थी आहे. आरोग्याच्या कारणास्तव काही प्रोग्रामिंग क्लासेस चुकवल्यानंतर, मला स्टॅक आणि क्यू सारख्या विषयांच्या आकलनाच्या अभावाचा सामना करावा लागला. चाचणी आणि त्रुटीद्वारे, काही दिवसांनंतर, शेवटी ते काय आहे आणि ते कशासह खाल्ले आहे हे माझ्या लक्षात आले. जेणेकरून तुमची समजूत काढायला जास्त वेळ लागणार नाही, या लेखात मी "स्टॅक" म्हणजे काय, ते कसे आणि कोणत्या उदाहरणांनी समजले याबद्दल बोलेन. तुम्हाला ते आवडल्यास, मी दुसरा भाग लिहीन, जो "रांग" सारख्या संकल्पनेला स्पर्श करेल.

सिद्धांत

विकिपीडियावर स्टॅकची व्याख्या अशी आहे:

स्टॅक (इंग्रजी स्टॅक - स्टॅक; स्टॅक वाचणे) हा एक अमूर्त डेटा प्रकार आहे, जो LIFO तत्त्वानुसार आयोजित केलेल्या घटकांची सूची आहे (इंग्रजी लास्ट इन - फर्स्ट आउट, "लास्ट इन - फर्स्ट आउट").

बऱ्यापैकी पूर्ण व्याख्या, परंतु नवशिक्यांसाठी समजणे थोडे कठीण आहे.

म्हणून, मी प्रथम ज्या गोष्टीवर लक्ष केंद्रित करू इच्छितो ते म्हणजे जीवनातील गोष्टींच्या स्वरूपात स्टॅकचे प्रतिनिधित्व करणे. माझ्या मनात आलेला पहिला अर्थ पुस्तकांच्या स्टॅकच्या स्वरूपात होता, जिथे सर्वात वरचे पुस्तक आहे.


खरं तर, स्टॅक कोणत्याही वस्तूंचा स्टॅक म्हणून दर्शविला जाऊ शकतो, मग तो पत्रके, नोटबुक, शर्ट इत्यादींचा स्टॅक असो, परंतु मला वाटते की पुस्तकांसह उदाहरण सर्वात अनुकूल असेल.

तर, स्टॅकमध्ये काय असते?

स्टॅकमध्ये सेल असतात (उदाहरणार्थ, ही पुस्तके आहेत), जी काही डेटा असलेली रचना आणि पुढील घटकाकडे या संरचनेच्या प्रकारासाठी पॉइंटर म्हणून दर्शविली जाते.
अवघड? काही हरकत नाही, चला ते शोधूया.

हे चित्र योजनाबद्धपणे स्टॅक दाखवते. "डेटा/*पुढील" फॉर्मचा ब्लॉक आमचा सेल आहे. *पुढे, जसे आपण पाहतो, पुढील घटकाकडे निर्देश करतो, दुसऱ्या शब्दांत, *पुढील पॉइंटर पुढील सेलचा पत्ता संग्रहित करतो. *TOP पॉइंटर स्टॅकच्या वरच्या बाजूस निर्देशित करतो, म्हणजेच तो त्याचा पत्ता संग्रहित करतो.


आम्ही सिद्धांत पूर्ण केले, चला सराव करू.

सराव करा

प्रथम आपल्याला एक रचना तयार करण्याची आवश्यकता आहे जी आपला "सेल" असेल


C++ कोड

struct comp ( // संरचना याला कॉम्प (शब्द घटकातून) int डेटा म्हणतात; // काही डेटा (कोणताही असू शकतो, उदाहरणार्थ आपण int की लिहू शकता; चार डेटा; आपण काही इतर डेटा देखील जोडू शकता) comp *next;/ /कंप टाइप पॉइंटर पुढील घटकासाठी);


आमचा पॉइंटर कॉम्प प्रकारचा का आहे किंवा अधिक तंतोतंत, कॉम्प स्ट्रक्चर प्रकाराचा पॉइंटर का आहे हे नवशिक्यांना समजू शकत नाही. मी समजावून सांगतो, *पुढील पॉइंटर कॉम्प स्ट्रक्चर साठवण्यासाठी, त्याला या स्ट्रक्चरचा प्रकार सूचित करणे आवश्यक आहे. दुसऱ्या शब्दांत, पॉइंटर काय संचयित करेल ते दर्शवा.


एकदा आमच्याकडे "सेल" सेट झाल्यानंतर, फंक्शन्स तयार करण्यासाठी पुढे जाऊ या.

कार्ये

"स्टॅक" तयार करणे/"स्टॅक" मध्ये एक घटक जोडण्याचे कार्य

घटक जोडताना, आमच्याकडे दोन परिस्थिती असतील:

  • स्टॅक रिक्त आहे आणि तयार करणे आवश्यक आहे
  • स्टॅक आधीपासून अस्तित्वात आहे आणि तुम्हाला त्यात एक नवीन घटक जोडण्याची आवश्यकता आहे
मी फंक्शनला s_push म्हणेन, चला कोडकडे जाऊ या.

C++ कोड

void s_push(comp **top, int D) ( // फंक्शन ऑफ टाईप void (काहीही परत करत नाही) जे स्टॅकच्या शीर्षस्थानी पॉइंटर घेऊन जाते आणि एक व्हेरिएबल जे सेल कॉम्प *q वर लिहिले जाईल; // तयार करा संरचनेचा एक नवीन पॉइंटर q = नवीन कॉम्प(); element if (शीर्ष == NULL) ( // जर तेथे शिरोबिंदू नसेल, म्हणजे, स्टॅक रिकामा असेल * top = q; // स्टॅकचा वरचा भाग नवीन घटक असेल) अन्यथा // स्टॅक नसल्यास रिक्त ( q->पुढील = *शीर्ष; //आम्ही नवीन घटकापासून शीर्षस्थानी कनेक्शन काढतो. म्हणजेच, आम्ही पुस्तक स्टॅकच्या शीर्षस्थानी ठेवतो. *शीर्ष = q; // शीर्षस्थानी आहे हे दर्शवा आता एक नवीन घटक))


चला ते थोडे अधिक तपशीलाने पाहू.
प्रथम, फंक्शन **टॉप, म्हणजे पॉइंटर टू पॉइंटर का स्वीकारते, हे तुम्हाला अधिक स्पष्ट करण्यासाठी, मी या समस्येचा विचार नंतरसाठी सोडेन. दुसरे म्हणजे, याबद्दल अधिक तपशीलवार बोलूया q->पुढील = *शीर्षआणि त्याचा अर्थ काय याबद्दल -> .


-> म्हणजे, ढोबळपणे बोलायचे झाल्यास, आपण आपल्या संरचनेत जातो आणि तिथून या संरचनेचा एक घटक बाहेर काढतो. ओळीत q->पुढील = *शीर्षआम्ही आमच्या सेलच्या पुढील घटक *पुढील एक पॉइंटर घेतो आणि त्यास स्टॅक *टॉपच्या शीर्षस्थानी पॉइंटरने बदलतो. दुसऱ्या शब्दांत, आम्ही नवीन घटकापासून स्टॅकच्या शीर्षस्थानी कनेक्शन बनवतो. येथे काहीही क्लिष्ट नाही, सर्वकाही पुस्तकांसारखे आहे. आम्ही नवीन पुस्तक स्टॅकच्या शीर्षस्थानी ठेवतो, म्हणजेच आम्ही नवीन पुस्तकापासून पुस्तकांच्या स्टॅकच्या शीर्षस्थानी कनेक्शन काढतो. यानंतर, नवीन पुस्तक आपोआप शीर्षस्थानी बनते, स्टॅक हा पुस्तकांचा स्टॅक नसल्यामुळे, आम्हाला सूचित करणे आवश्यक आहे की नवीन घटक शीर्ष आहे, यासाठी आम्ही लिहितो: *शीर्ष = q;.

डेटावर आधारित "स्टॅक" मधून घटक काढून टाकण्याचे कार्य

सेलच्या डेटाची संख्या (q->डेटा) आपण स्वतः नियुक्त केलेल्या संख्येइतकी असल्यास हे फंक्शन स्टॅकमधून घटक काढून टाकेल.


खालील पर्याय असू शकतात:

  • आम्हाला जो सेल काढायचा आहे तो स्टॅकचा वरचा भाग आहे
  • आपल्याला हटवण्याची गरज असलेला सेल शेवटी किंवा दोन पेशींमधील आहे

C++ कोड

void s_delete_key(comp **top, int N) (// एक फंक्शन जे टॉप टॉप आणि हटवायचा क्रमांक घेते comp *q = *टॉप; // कॉम्प टाइप पॉइंटर तयार करा आणि वरच्या बाजूला समान करा (ठेवा). stack comp *prev = NULL;//आम्ही मागील घटकासाठी एक पॉइंटर तयार करतो, सुरुवातीपासून ते रिकामे असेल (q != NULL) (// पॉइंटर q रिक्त नसताना, आम्ही कोड कार्यान्वित करू. लूपमध्ये, जर ते अद्याप रिकामे असेल तर लूप संपेल जर (q-> डेटा == N) (//जर घटकाचा डेटा आपल्याला काढण्यासाठी आवश्यक असलेल्या संख्येइतका असेल तर (q == *शीर्ष) ( //असा पॉईंटर वरच्या बरोबरीचा असेल, तर एक घटक आहे जो आपल्याला काढून टाकण्याची गरज आहे - शीर्ष *शीर्ष = q->पुढील;// शिरोबिंदूला पुढील घटक मुक्त (q) वर हलवा;//स्पष्ट सेल q->डेटा = NULL; // पुढे, त्रुटी टाळण्यासाठी, आम्ही रिमोट सेलमध्ये व्हेरिएबल्स रीसेट करतो, कारण काही कंपायलरमध्ये रिमोट सेलमध्ये NULL व्हेरिएबल्स नसतात, परंतु अक्षरशः "मेमरी रीडिंग अशक्य आहे" किंवा संख्या “-2738568384” किंवा इतर, कंपायलर q->next = NULL ) वर अवलंबून//जर घटक शेवटचा असेल किंवा इतर दोन घटकांमधील असेल (पूर्वी->पुढील = q ->पुढील;// कनेक्शन काढा मागील घटकापासून पुढील विनामूल्य(q);//सेल साफ करा q->डेटा = NULL;// व्हेरिएबल्स q->पुढील = NULL;


) ) // जर घटकाचा डेटा नंबरच्या बरोबरीचा नसेल तर आम्हाला prev = q काढून टाकणे आवश्यक आहे; //वर्तमान सेल मागील एक प्रमाणे लक्षात ठेवा q = q->पुढील;//पॉइंटर q पुढील घटकाकडे हलवा) ) या प्रकरणात पॉइंटर q नोटपॅडमधील पॉईंटर सारखीच भूमिका बजावते जोपर्यंत तो NULL(च्या समान होत नाही) तो संपूर्ण स्टॅकमध्ये चालतो;असताना(q != NULL)

घटक काढून टाकणे अधिक चांगल्या प्रकारे समजून घेण्यासाठी, पुस्तकांच्या आधीच परिचित असलेल्या स्टॅकशी साधर्म्य काढू या. आम्हाला वरून एखादे पुस्तक काढायचे असल्यास, आम्ही ते काढून टाकतो आणि त्याखालील पुस्तक सर्वात वरचे बनते. येथेही तेच आहे, फक्त सुरूवातीलाच पुढील घटक शीर्षस्थानी होईल हे निश्चित केले पाहिजे *शीर्ष = q->पुढील;आणि फक्त नंतर घटक हटवा मोफत(q);


जर काढायचे पुस्तक दोन पुस्तकांच्या मध्ये किंवा पुस्तक आणि टेबलच्या मध्ये असेल तर, मागील पुस्तक पुढील पुस्तकावर किंवा टेबलवर पडेल. जसे आपण आधीच समजले आहे की, आमचे पुस्तक एक सेल आहे आणि सारणी NULL आहे, म्हणजेच पुढील घटक नाही. हे पुस्तकांप्रमाणेच बाहेर वळते, आम्ही नियुक्त करतो की मागील सेल पुढील सेलशी कनेक्ट केला जाईल prev->next = q->पुढील;, हे लक्षात घेण्यासारखे आहे मागील->पुढीलसेल किंवा शून्याच्या समान असू शकते, जर q->पुढील = NULL, म्हणजे, सेल नाही (पुस्तक टेबलवर पडेल), त्यानंतर आम्ही सेल साफ करतो मोफत(q).

हे देखील लक्षात घेण्यासारखे आहे की जर हे कनेक्शन केले गेले नाही तर, हटविलेल्या सेलच्या नंतर असलेल्या पेशींचा विभाग प्रवेश करण्यायोग्य होईल, कारण एका सेलला दुसऱ्या सेलशी जोडणारे कनेक्शन गमावले जाईल आणि हा विभाग मेमरीमध्ये गमावला जाईल.

स्टॅक डिस्प्ले फंक्शन

सर्वात सोपा कार्य:


C++ कोड

void s_print(comp *top) ( //स्टॅकच्या शीर्षस्थानी एक पॉइंटर स्वीकारतो comp *q = top; // q वर सेट करा तर (q) ( // जोपर्यंत q रिकामा नाही (तर(q) ) हे while(q != NULL )) printf_s("%i", q->डेटा) च्या समतुल्य आहे;//स्टॅक सेलचा डेटा प्रदर्शित करा q = q->पुढील;// ते प्रदर्शित केल्यानंतर, q वर हलवा पुढील घटक (सेल) ) )


येथे मला वाटते की सर्व काही स्पष्ट आहे, मला फक्त असे म्हणायचे आहे की q हा स्लाइडर म्हणून समजला जावा, तो वरच्या सर्व सेलवर चालतो जिथे आपण ते सुरुवातीला सेट केले आहे: *q = शीर्ष;, शेवटच्या घटकापर्यंत.

मुख्य कार्य

ठीक आहे, आम्ही स्टॅकसह कार्य करण्यासाठी मुख्य कार्ये लिहून ठेवली आहेत आणि त्यांना कॉल करा.
चला कोड पाहू:

C++ कोड

void main() ( comp *top = NULL; // प्रोग्रामच्या सुरुवातीला आपल्याकडे रांग नाही, म्हणून शीर्ष नाही, आम्ही त्यास NULL मूल्य देतो // पुढे आपण 1 ते 5 पर्यंत संख्या जोडण्यास सुरवात करतो. आमचे स्टॅक s_push(&top, 2); s_push(&top, 5); प्रिंट s_delete_key(&top, 4); //मग आम्ही 4 हटवतो, स्टॅकला 5321 printf_s("\n");//नवीन ओळ s_print(top);//print system("pause");/ मिळते /विराम द्या)


फंक्शनच्या व्हर्टेक्स पॉईंटरला पॉइंटर का पास केले ते पाहू. वस्तुस्थिती अशी आहे की जर आपण फंक्शनमध्ये शिरोबिंदूसाठी फक्त एक पॉइंटर आणला, तर "स्टॅक" तयार होईल आणि फक्त मुख्य फंक्शनमध्ये व्हर्टेक्स NULL राहील; पॉइंटरला पॉइंटर पास करून, आपण मुख्य फंक्शनमध्ये *टॉप व्हर्टेक्स बदलतो. असे दिसून आले की फंक्शनने स्टॅक बदलल्यास, आपल्याला पॉइंटरला पॉइंटरसह एक शिरोबिंदू पास करणे आवश्यक आहे, जसे आपण s_push, s_delete_key फंक्शनमध्ये केले. s_print फंक्शनमध्ये, "स्टॅक" बदलू नये, म्हणून आम्ही फक्त एक पॉइंटर शीर्षस्थानी देतो.
1,2,3,4,5 या आकड्यांऐवजी तुम्ही int टाईप व्हेरिएबल्स देखील वापरू शकता.

निष्कर्ष

पूर्ण प्रोग्राम कोड:


C++ कोड

#समाविष्ट करा ; #समाविष्ट करा ; struct comp ( // संरचना नावाचे comp int डेटा; // काही डेटा (तुमचा आवडता असू शकतो, उदाहरणार्थ तुम्ही int की लिहू शकता; char Data; किंवा काही अन्य डेटा जोडू शकता) comp *next; // पॉइंटर ऑफ टाइप कॉम्प पुढील घटक); void s_push(comp **top, int D) ( // फंक्शन ऑफ टाईप व्हॉइड (काहीही मिळत नाही) जे स्टॅकच्या शीर्षस्थानी पॉइंटर घेऊन जाते आणि एक व्हेरिएबल जे सेल कॉम्प *q वर लिहिले जाईल; // तयार करा नवीन पॉइंटर q, ज्याला आम्ही वरच्या स्टॅकशी समतुल्य करतो, हे आमचे नवीन घटक आहे q = new comp(); if (शीर्ष == NULL) ( // शिरोबिंदू क्रमांक असल्यास, म्हणजे, स्टॅक रिकामा असेल * top = q; // स्टॅकचा वरचा भाग नवीन घटक असेल) अन्यथा // स्टॅक रिक्त नसल्यास ( q->नेक्स्ट = *टॉप; //आम्ही टॉप स्टॅकवर एक जोडणी काढतो घटक) ) void s_delete_key(comp **top, int N) (// एक फंक्शन जे शीर्ष आणि हटवायचे क्रमांक घेते comp *q = *top; // कॉम्प टाइपचा एक पॉइंटर तयार करा आणि ते समान करा (ठेवा) स्टॅक comp च्या शीर्षस्थानी *prev = NULL;// मागील घटकासाठी एक पॉइंटर तयार करा, सुरुवातीपासून ते रिक्त असेल (q != NULL) (//पॉइंटर q रिक्त होईपर्यंत, आम्ही ते तपासू. जर तरीही लूप संपू द्या if (q->डेटा == N) (//जर घटकाचा डेटा आपल्याला हटवायचा आहे त्या संख्येइतका असेल तर (q == *टॉप) (//असे असल्यास पॉइंटर समान शीर्ष आहे, म्हणजे, घटक हटवायचा आहे - टॉप *टॉप = q->पुढील;//टॉपला पुढील घटकावर विनामूल्य हलवा(q);//सेल साफ करा q->डेटा = NULL; // पुढे, त्रुटी टाळण्यासाठी, आम्ही रिमोट सेलमधील व्हेरिएबल्स शून्यावर रीसेट करतो, कारण काही कंपायलरमध्ये रिमोट सेलमध्ये व्हेरिएबल्ससाठी NULL मूल्ये नसतात, परंतु अक्षरशः "मेमरी वाचन अशक्य आहे" किंवा "-2738568384" संख्या. किंवा इतर, कंपाइलरवर अवलंबून. = NULL)) printf_s("%i", q->डेटा);//स्टॅक सेलचा डेटा प्रदर्शित करा q = q->पुढील;// ते प्रदर्शित केल्यानंतर, q ला पुढील घटकावर हलवा (सेल) ) void main () ( comp *top = NULL; // प्रोग्रामच्या सुरुवातीला आपल्याकडे रांग नाही, म्हणून शीर्ष नाही, आम्ही त्यास NULL मूल्य देतो // पुढे आपण 1 ते 5 पर्यंत संख्या जोडण्यास सुरवात करतो. आमचे स्टॅक s_push(&top, 2); // मग आम्ही 4 डिलीट करतो, स्टॅकला 5321 printf_s("\n");// अनुवादित करतो s_print(top);// प्रिंट सिस्टम ("विराम द्या");//विराम)

अंमलबजावणी परिणाम



घटक सतत स्टॅकच्या शीर्षस्थानी जोडले जात असल्याने, घटक उलट क्रमाने प्रदर्शित केले जातील.



शेवटी, तुम्ही माझ्या लेखासाठी दिलेल्या वेळेबद्दल मी तुमचे आभार मानू इच्छितो, मला आशा आहे की या सामग्रीने काही नवशिक्या प्रोग्रामरना "स्टॅक" म्हणजे काय, ते कसे वापरावे हे समजण्यास मदत केली आणि भविष्यात त्यांच्याकडे यापुढे राहणार नाही. समस्या टिप्पण्यांमध्ये तुमचे मत लिहा, तसेच मी भविष्यात माझे लेख कसे सुधारू शकतो. आपले लक्ष दिल्याबद्दल धन्यवाद.

टॅग: टॅग जोडा

नमस्कार, मी एका तांत्रिक विद्यापीठात द्वितीय वर्षाचा विद्यार्थी आहे. आरोग्याच्या कारणास्तव काही प्रोग्रामिंग क्लासेस चुकवल्यानंतर, मला स्टॅक आणि क्यू सारख्या विषयांच्या आकलनाच्या अभावाचा सामना करावा लागला. चाचणी आणि त्रुटीद्वारे, काही दिवसांनंतर, शेवटी ते काय आहे आणि ते कशासह खाल्ले आहे हे माझ्या लक्षात आले. जेणेकरून तुमची समजूत काढायला जास्त वेळ लागणार नाही, या लेखात मी "स्टॅक" म्हणजे काय, ते कसे आणि कोणत्या उदाहरणांनी समजले याबद्दल बोलेन. तुम्हाला ते आवडल्यास, मी दुसरा भाग लिहीन, जो "रांग" सारख्या संकल्पनेला स्पर्श करेल.

सिद्धांत

विकिपीडियावर स्टॅकची व्याख्या अशी आहे:

स्टॅक (इंग्रजी स्टॅक - स्टॅक; स्टॅक वाचणे) हा एक अमूर्त डेटा प्रकार आहे, जो LIFO तत्त्वानुसार आयोजित केलेल्या घटकांची सूची आहे (इंग्रजी लास्ट इन - फर्स्ट आउट, "लास्ट इन - फर्स्ट आउट").

बऱ्यापैकी पूर्ण व्याख्या, परंतु नवशिक्यांसाठी समजणे थोडे कठीण आहे.

म्हणून, मी प्रथम ज्या गोष्टीवर लक्ष केंद्रित करू इच्छितो ते म्हणजे जीवनातील गोष्टींच्या स्वरूपात स्टॅकचे प्रतिनिधित्व करणे. माझ्या मनात आलेला पहिला अर्थ पुस्तकांच्या स्टॅकच्या स्वरूपात होता, जिथे सर्वात वरचे पुस्तक आहे.


खरं तर, स्टॅक कोणत्याही वस्तूंचा स्टॅक म्हणून दर्शविला जाऊ शकतो, मग तो पत्रके, नोटबुक, शर्ट इत्यादींचा स्टॅक असो, परंतु मला वाटते की पुस्तकांसह उदाहरण सर्वात अनुकूल असेल.

तर, स्टॅकमध्ये काय असते?

स्टॅकमध्ये सेल असतात (उदाहरणार्थ, ही पुस्तके आहेत), जी काही डेटा असलेली रचना आणि पुढील घटकाकडे या संरचनेच्या प्रकारासाठी पॉइंटर म्हणून दर्शविली जाते.
अवघड? काही हरकत नाही, चला ते शोधूया.

हे चित्र योजनाबद्धपणे स्टॅक दाखवते. "डेटा/*पुढील" फॉर्मचा ब्लॉक आमचा सेल आहे. *पुढे, जसे आपण पाहतो, पुढील घटकाकडे निर्देश करतो, दुसऱ्या शब्दांत, *पुढील पॉइंटर पुढील सेलचा पत्ता संग्रहित करतो. *TOP पॉइंटर स्टॅकच्या वरच्या बाजूस निर्देशित करतो, म्हणजेच तो त्याचा पत्ता संग्रहित करतो.


आम्ही सिद्धांत पूर्ण केले, चला सराव करू.

सराव करा

प्रथम आपल्याला एक रचना तयार करण्याची आवश्यकता आहे जी आपला "सेल" असेल


C++ कोड

struct comp ( // संरचना याला कॉम्प (शब्द घटकातून) int डेटा म्हणतात; // काही डेटा (कोणताही असू शकतो, उदाहरणार्थ आपण int की लिहू शकता; चार डेटा; आपण काही इतर डेटा देखील जोडू शकता) comp *next;/ /कंप टाइप पॉइंटर पुढील घटकासाठी);


आमचा पॉइंटर कॉम्प प्रकारचा का आहे किंवा अधिक तंतोतंत, कॉम्प स्ट्रक्चर प्रकाराचा पॉइंटर का आहे हे नवशिक्यांना समजू शकत नाही. मी समजावून सांगतो, *पुढील पॉइंटर कॉम्प स्ट्रक्चर साठवण्यासाठी, त्याला या स्ट्रक्चरचा प्रकार सूचित करणे आवश्यक आहे. दुसऱ्या शब्दांत, पॉइंटर काय संचयित करेल ते दर्शवा.


एकदा आमच्याकडे "सेल" सेट झाल्यानंतर, फंक्शन्स तयार करण्यासाठी पुढे जाऊ या.

कार्ये

"स्टॅक" तयार करणे/"स्टॅक" मध्ये एक घटक जोडण्याचे कार्य

घटक जोडताना, आमच्याकडे दोन परिस्थिती असतील:

  • स्टॅक रिक्त आहे आणि तयार करणे आवश्यक आहे
  • स्टॅक आधीपासून अस्तित्वात आहे आणि तुम्हाला त्यात एक नवीन घटक जोडण्याची आवश्यकता आहे
मी फंक्शनला s_push म्हणेन, चला कोडकडे जाऊ या.

C++ कोड

void s_push(comp **top, int D) ( // फंक्शन ऑफ टाईप void (काहीही परत करत नाही) जे स्टॅकच्या शीर्षस्थानी पॉइंटर घेऊन जाते आणि एक व्हेरिएबल जे सेल कॉम्प *q वर लिहिले जाईल; // तयार करा संरचनेचा एक नवीन पॉइंटर q = नवीन कॉम्प(); element if (शीर्ष == NULL) ( // जर तेथे शिरोबिंदू नसेल, म्हणजे, स्टॅक रिकामा असेल * top = q; // स्टॅकचा वरचा भाग नवीन घटक असेल) अन्यथा // स्टॅक नसल्यास रिक्त ( q->पुढील = *शीर्ष; //आम्ही नवीन घटकापासून शीर्षस्थानी कनेक्शन काढतो. म्हणजेच, आम्ही पुस्तक स्टॅकच्या शीर्षस्थानी ठेवतो. *शीर्ष = q; // शीर्षस्थानी आहे हे दर्शवा आता एक नवीन घटक))


चला ते थोडे अधिक तपशीलाने पाहू.
प्रथम, फंक्शन **टॉप, म्हणजे पॉइंटर टू पॉइंटर का स्वीकारते, हे तुम्हाला अधिक स्पष्ट करण्यासाठी, मी या समस्येचा विचार नंतरसाठी सोडेन. दुसरे म्हणजे, याबद्दल अधिक तपशीलवार बोलूया q->पुढील = *शीर्षआणि त्याचा अर्थ काय याबद्दल -> .


-> म्हणजे, ढोबळपणे बोलायचे झाल्यास, आपण आपल्या संरचनेत जातो आणि तिथून या संरचनेचा एक घटक बाहेर काढतो. ओळीत q->पुढील = *शीर्षआम्ही आमच्या सेलच्या पुढील घटक *पुढील एक पॉइंटर घेतो आणि त्यास स्टॅक *टॉपच्या शीर्षस्थानी पॉइंटरने बदलतो. दुसऱ्या शब्दांत, आम्ही नवीन घटकापासून स्टॅकच्या शीर्षस्थानी कनेक्शन बनवतो. येथे काहीही क्लिष्ट नाही, सर्वकाही पुस्तकांसारखे आहे. आम्ही नवीन पुस्तक स्टॅकच्या शीर्षस्थानी ठेवतो, म्हणजेच आम्ही नवीन पुस्तकापासून पुस्तकांच्या स्टॅकच्या शीर्षस्थानी कनेक्शन काढतो. यानंतर, नवीन पुस्तक आपोआप शीर्षस्थानी बनते, स्टॅक हा पुस्तकांचा स्टॅक नसल्यामुळे, आम्हाला सूचित करणे आवश्यक आहे की नवीन घटक शीर्ष आहे, यासाठी आम्ही लिहितो: *शीर्ष = q;.

डेटावर आधारित "स्टॅक" मधून घटक काढून टाकण्याचे कार्य

सेलच्या डेटाची संख्या (q->डेटा) आपण स्वतः नियुक्त केलेल्या संख्येइतकी असल्यास हे फंक्शन स्टॅकमधून घटक काढून टाकेल.


खालील पर्याय असू शकतात:

  • आम्हाला जो सेल काढायचा आहे तो स्टॅकचा वरचा भाग आहे
  • आपल्याला हटवण्याची गरज असलेला सेल शेवटी किंवा दोन पेशींमधील आहे

C++ कोड

void s_delete_key(comp **top, int N) (// एक फंक्शन जे टॉप टॉप आणि हटवायचा क्रमांक घेते comp *q = *टॉप; // कॉम्प टाइप पॉइंटर तयार करा आणि वरच्या बाजूला समान करा (ठेवा). stack comp *prev = NULL;//आम्ही मागील घटकासाठी एक पॉइंटर तयार करतो, सुरुवातीपासून ते रिकामे असेल (q != NULL) (// पॉइंटर q रिक्त नसताना, आम्ही कोड कार्यान्वित करू. लूपमध्ये, जर ते अद्याप रिकामे असेल तर लूप संपेल जर (q-> डेटा == N) (//जर घटकाचा डेटा आपल्याला काढण्यासाठी आवश्यक असलेल्या संख्येइतका असेल तर (q == *शीर्ष) ( //असा पॉईंटर वरच्या बरोबरीचा असेल, तर एक घटक आहे जो आपल्याला काढून टाकण्याची गरज आहे - शीर्ष *शीर्ष = q->पुढील;// शिरोबिंदूला पुढील घटक मुक्त (q) वर हलवा;//स्पष्ट सेल q->डेटा = NULL; // पुढे, त्रुटी टाळण्यासाठी, आम्ही रिमोट सेलमध्ये व्हेरिएबल्स रीसेट करतो, कारण काही कंपायलरमध्ये रिमोट सेलमध्ये NULL व्हेरिएबल्स नसतात, परंतु अक्षरशः "मेमरी रीडिंग अशक्य आहे" किंवा संख्या “-2738568384” किंवा इतर, कंपायलर q->next = NULL ) वर अवलंबून//जर घटक शेवटचा असेल किंवा इतर दोन घटकांमधील असेल (पूर्वी->पुढील = q ->पुढील;// कनेक्शन काढा मागील घटकापासून पुढील विनामूल्य(q);//सेल साफ करा q->डेटा = NULL;// व्हेरिएबल्स q->पुढील = NULL;


) ) // जर घटकाचा डेटा नंबरच्या बरोबरीचा नसेल तर आम्हाला prev = q काढून टाकणे आवश्यक आहे; //वर्तमान सेल मागील एक प्रमाणे लक्षात ठेवा q = q->पुढील;//पॉइंटर q पुढील घटकाकडे हलवा) ) या प्रकरणात पॉइंटर q नोटपॅडमधील पॉईंटर सारखीच भूमिका बजावते जोपर्यंत तो NULL(च्या समान होत नाही) तो संपूर्ण स्टॅकमध्ये चालतो;असताना(q != NULL)

घटक काढून टाकणे अधिक चांगल्या प्रकारे समजून घेण्यासाठी, पुस्तकांच्या आधीच परिचित असलेल्या स्टॅकशी साधर्म्य काढू या. आम्हाला वरून एखादे पुस्तक काढायचे असल्यास, आम्ही ते काढून टाकतो आणि त्याखालील पुस्तक सर्वात वरचे बनते. येथेही तेच आहे, फक्त सुरूवातीलाच पुढील घटक शीर्षस्थानी होईल हे निश्चित केले पाहिजे *शीर्ष = q->पुढील;आणि फक्त नंतर घटक हटवा मोफत(q);


जर काढायचे पुस्तक दोन पुस्तकांच्या मध्ये किंवा पुस्तक आणि टेबलच्या मध्ये असेल तर, मागील पुस्तक पुढील पुस्तकावर किंवा टेबलवर पडेल. जसे आपण आधीच समजले आहे की, आमचे पुस्तक एक सेल आहे आणि सारणी NULL आहे, म्हणजेच पुढील घटक नाही. हे पुस्तकांप्रमाणेच बाहेर वळते, आम्ही नियुक्त करतो की मागील सेल पुढील सेलशी कनेक्ट केला जाईल prev->next = q->पुढील;, हे लक्षात घेण्यासारखे आहे मागील->पुढीलसेल किंवा शून्याच्या समान असू शकते, जर q->पुढील = NULL, म्हणजे, सेल नाही (पुस्तक टेबलवर पडेल), त्यानंतर आम्ही सेल साफ करतो मोफत(q).

हे देखील लक्षात घेण्यासारखे आहे की जर हे कनेक्शन केले गेले नाही तर, हटविलेल्या सेलच्या नंतर असलेल्या पेशींचा विभाग प्रवेश करण्यायोग्य होईल, कारण एका सेलला दुसऱ्या सेलशी जोडणारे कनेक्शन गमावले जाईल आणि हा विभाग मेमरीमध्ये गमावला जाईल.

स्टॅक डिस्प्ले फंक्शन

सर्वात सोपा कार्य:


C++ कोड

void s_print(comp *top) ( //स्टॅकच्या शीर्षस्थानी एक पॉइंटर स्वीकारतो comp *q = top; // q वर सेट करा तर (q) ( // जोपर्यंत q रिकामा नाही (तर(q) ) हे while(q != NULL )) printf_s("%i", q->डेटा) च्या समतुल्य आहे;//स्टॅक सेलचा डेटा प्रदर्शित करा q = q->पुढील;// ते प्रदर्शित केल्यानंतर, q वर हलवा पुढील घटक (सेल) ) )


येथे मला वाटते की सर्व काही स्पष्ट आहे, मला फक्त असे म्हणायचे आहे की q हा स्लाइडर म्हणून समजला जावा, तो वरच्या सर्व सेलवर चालतो जिथे आपण ते सुरुवातीला सेट केले आहे: *q = शीर्ष;, शेवटच्या घटकापर्यंत.

मुख्य कार्य

ठीक आहे, आम्ही स्टॅकसह कार्य करण्यासाठी मुख्य कार्ये लिहून ठेवली आहेत आणि त्यांना कॉल करा.
चला कोड पाहू:

C++ कोड

void main() ( comp *top = NULL; // प्रोग्रामच्या सुरुवातीला आपल्याकडे रांग नाही, म्हणून शीर्ष नाही, आम्ही त्यास NULL मूल्य देतो // पुढे आपण 1 ते 5 पर्यंत संख्या जोडण्यास सुरवात करतो. आमचे स्टॅक s_push(&top, 2); s_push(&top, 5); प्रिंट s_delete_key(&top, 4); //मग आम्ही 4 हटवतो, स्टॅकला 5321 printf_s("\n");//नवीन ओळ s_print(top);//print system("pause");/ मिळते /विराम द्या)


फंक्शनच्या व्हर्टेक्स पॉईंटरला पॉइंटर का पास केले ते पाहू. वस्तुस्थिती अशी आहे की जर आपण फंक्शनमध्ये शिरोबिंदूसाठी फक्त एक पॉइंटर आणला, तर "स्टॅक" तयार होईल आणि फक्त मुख्य फंक्शनमध्ये व्हर्टेक्स NULL राहील; पॉइंटरला पॉइंटर पास करून, आपण मुख्य फंक्शनमध्ये *टॉप व्हर्टेक्स बदलतो. असे दिसून आले की फंक्शनने स्टॅक बदलल्यास, आपल्याला पॉइंटरला पॉइंटरसह एक शिरोबिंदू पास करणे आवश्यक आहे, जसे आपण s_push, s_delete_key फंक्शनमध्ये केले. s_print फंक्शनमध्ये, "स्टॅक" बदलू नये, म्हणून आम्ही फक्त एक पॉइंटर शीर्षस्थानी देतो.
1,2,3,4,5 या आकड्यांऐवजी तुम्ही int टाईप व्हेरिएबल्स देखील वापरू शकता.

निष्कर्ष

पूर्ण प्रोग्राम कोड:


C++ कोड

#समाविष्ट करा ; #समाविष्ट करा ; struct comp ( // संरचना नावाचे comp int डेटा; // काही डेटा (तुमचा आवडता असू शकतो, उदाहरणार्थ तुम्ही int की लिहू शकता; char Data; किंवा काही अन्य डेटा जोडू शकता) comp *next; // पॉइंटर ऑफ टाइप कॉम्प पुढील घटक); void s_push(comp **top, int D) ( // फंक्शन ऑफ टाईप व्हॉइड (काहीही मिळत नाही) जे स्टॅकच्या शीर्षस्थानी पॉइंटर घेऊन जाते आणि एक व्हेरिएबल जे सेल कॉम्प *q वर लिहिले जाईल; // तयार करा नवीन पॉइंटर q, ज्याला आम्ही वरच्या स्टॅकशी समतुल्य करतो, हे आमचे नवीन घटक आहे q = new comp(); if (शीर्ष == NULL) ( // शिरोबिंदू क्रमांक असल्यास, म्हणजे, स्टॅक रिकामा असेल * top = q; // स्टॅकचा वरचा भाग नवीन घटक असेल) अन्यथा // स्टॅक रिक्त नसल्यास ( q->नेक्स्ट = *टॉप; //आम्ही टॉप स्टॅकवर एक जोडणी काढतो घटक) ) void s_delete_key(comp **top, int N) (// एक फंक्शन जे शीर्ष आणि हटवायचे क्रमांक घेते comp *q = *top; // कॉम्प टाइपचा एक पॉइंटर तयार करा आणि ते समान करा (ठेवा) स्टॅक comp च्या शीर्षस्थानी *prev = NULL;// मागील घटकासाठी एक पॉइंटर तयार करा, सुरुवातीपासून ते रिक्त असेल (q != NULL) (//पॉइंटर q रिक्त होईपर्यंत, आम्ही ते तपासू. जर तरीही लूप संपू द्या if (q->डेटा == N) (//जर घटकाचा डेटा आपल्याला हटवायचा आहे त्या संख्येइतका असेल तर (q == *टॉप) (//असे असल्यास पॉइंटर समान शीर्ष आहे, म्हणजे, घटक हटवायचा आहे - टॉप *टॉप = q->पुढील;//टॉपला पुढील घटकावर विनामूल्य हलवा(q);//सेल साफ करा q->डेटा = NULL; // पुढे, त्रुटी टाळण्यासाठी, आम्ही रिमोट सेलमधील व्हेरिएबल्स शून्यावर रीसेट करतो, कारण काही कंपायलरमध्ये रिमोट सेलमध्ये व्हेरिएबल्ससाठी NULL मूल्ये नसतात, परंतु अक्षरशः "मेमरी वाचन अशक्य आहे" किंवा "-2738568384" संख्या. किंवा इतर, कंपाइलरवर अवलंबून. = NULL)) printf_s("%i", q->डेटा);//स्टॅक सेलचा डेटा प्रदर्शित करा q = q->पुढील;// ते प्रदर्शित केल्यानंतर, q ला पुढील घटकावर हलवा (सेल) ) void main () ( comp *top = NULL; // प्रोग्रामच्या सुरुवातीला आपल्याकडे रांग नाही, म्हणून शीर्ष नाही, आम्ही त्यास NULL मूल्य देतो // पुढे आपण 1 ते 5 पर्यंत संख्या जोडण्यास सुरवात करतो. आमचे स्टॅक s_push(&top, 2); // मग आम्ही 4 डिलीट करतो, स्टॅकला 5321 printf_s("\n");// अनुवादित करतो s_print(top);// प्रिंट सिस्टम ("विराम द्या");//विराम)

अंमलबजावणी परिणाम



घटक सतत स्टॅकच्या शीर्षस्थानी जोडले जात असल्याने, घटक उलट क्रमाने प्रदर्शित केले जातील.



शेवटी, तुम्ही माझ्या लेखासाठी दिलेल्या वेळेबद्दल मी तुमचे आभार मानू इच्छितो, मला आशा आहे की या सामग्रीने काही नवशिक्या प्रोग्रामरना "स्टॅक" म्हणजे काय, ते कसे वापरावे हे समजण्यास मदत केली आणि भविष्यात त्यांच्याकडे यापुढे राहणार नाही. समस्या टिप्पण्यांमध्ये तुमचे मत लिहा, तसेच मी भविष्यात माझे लेख कसे सुधारू शकतो. आपले लक्ष दिल्याबद्दल धन्यवाद.

प्रोग्रामिंगमध्ये प्रभुत्व मिळवताना, लवकरच किंवा नंतर प्रश्न उद्भवतो: " स्टॅक म्हणजे काय?".
मला वाटते की हे समजावून सांगण्याचा सर्वात स्पष्ट मार्ग म्हणजे असेंबली लँग्वेज प्रोग्राम (घाबरू नका) जो फक्त स्टॅकमध्ये डेटा जोडतो.

स्टॅकसर्व प्रोग्राम करण्यायोग्य तंत्रज्ञानामध्ये अंतर्निहित डेटा संरचना आहे. बऱ्याचदा, स्टॅकच्या ऑपरेशनच्या तत्त्वाची तुलना प्लेट्सच्या स्टॅकशी केली जाते: वरून दुसरा काढण्यासाठी, आपल्याला वरचा एक काढण्याची आवश्यकता आहे. स्टॅकला बऱ्याचदा मॅगझिन म्हटले जाते - बंदुकातील मॅगझिनशी साधर्म्य करून (शूटिंग शेवटच्या लोड केलेल्या काडतुसेने सुरू होईल).

या सगळ्याची गरज का आहे?

फंक्शन्स (सबरुटीन) वापरत नाही असा प्रोग्राम तुम्ही क्वचितच लिहू शकता. जेव्हा फंक्शन कॉल केले जाते, तेव्हा या सबरूटीनची अंमलबजावणी संपल्यानंतर परत येण्यासाठी पत्ता स्टॅकवर कॉपी केला जातो. त्याच्या अंमलबजावणीच्या शेवटी, स्टॅकमधून प्रोग्राम काउंटरवर पत्ता परत केला जातो आणि प्रोग्राम फंक्शननंतर बिंदूपासून कार्यान्वित केला जातो.
या सबरूटीनमध्ये वापरल्या जाणाऱ्या रजिस्टर्स स्टॅकवर ठेवणे देखील आवश्यक आहे (उच्च-स्तरीय भाषांमध्ये, हे कंपाइलरद्वारे केले जाते).
वरील सर्व तथाकथित हार्डवेअर स्टॅकसाठी वैशिष्ट्यपूर्ण आहे. मला आशा आहे की तुमच्या लक्षात येईल की ही डेटा रचना (LIFO - लास्ट इन, फर्स्ट आउट) केवळ निम्न स्तरावर काम करताना उपयुक्त नाही. बऱ्याचदा या क्रमाने डेटा संग्रहित करण्याची आवश्यकता असते (उदाहरणार्थ, अंकगणित अभिव्यक्ती विश्लेषित करण्यासाठी एक सुप्रसिद्ध अल्गोरिदम स्टॅकसह कार्य करण्यावर आधारित आहे), नंतर प्रोग्रामर सॉफ्टवेअर स्टॅक लागू करतात.

हे कसे कार्य करते?

चला स्टॅकसह कार्य करूया MSP430 फॅमिली कंट्रोलर्सचे उदाहरण वापरून. मी त्यांना निवडले कारण माझ्याकडे त्यांच्यासोबत काम करण्यासाठी वातावरण स्थापित केले होते.
MSP430 मध्ये, स्टॅक प्री-डिक्रिमेंटल डिझाइनवर आधारित आहे. त्या. तुम्ही स्टॅकवर डेटा लिहिण्यापूर्वी, ते स्टॅकच्या शीर्षस्थानी (टॉप प्लेटर) पत्ता कमी करते. पोस्ट-डिक्रिमेंटल/पोस्ट-इन्क्रिमेंटल (डेटा लिहिल्यानंतर स्टॅकच्या वरच्या भागाची वजाबाकी/जोडणे) आणि प्री-इन्क्रिमेंटल (लिहिण्यापूर्वी, टॉपचा पत्ता वाढवला जातो) देखील आहेत.
जर डेटा लिहिताना स्टॅकने त्याचा पत्ता वाढवला, तर तो वरच्या दिशेने वाढणारा स्टॅक आहे असे म्हटले जाते, जर ते कमी झाले तर ते खाली वाढत आहे असे म्हटले जाते.
SP रजिस्टर स्टॅकच्या वरच्या भागाचा पत्ता संग्रहित करण्यासाठी जबाबदार आहे.

तुम्ही बघू शकता, डीफॉल्ट शिरोबिंदू पत्ता 0x0A00 आहे.

या कार्यक्रमाचा विचार करा:

पुश #0123h ; स्टॅकच्या शीर्षस्थानी 0123h टाकणे (TOS); मेमरी MOV.W &0x0A00, R5 MOV.W &0x09FE, R6 मधून डेटा कॉपी करा; आणखी दोन संख्या लिहा PUSH #9250h PUSH #0000h ; स्टॅक POP R8 POP R9 POP R10 मधील पॉप डेटा

हा कार्यक्रम काय करतो?

PUSH कमांडसह आम्ही डेटा 0123h स्टॅकवर पुश करतो. असे दिसते की या कमांडद्वारे आम्ही 0x0A00 पत्त्यावर मेमरीमध्ये 0123h लिहू, परंतु आम्हाला आठवते की आमचा स्टॅक प्री-डिक्रिमेंटल आहे. म्हणून, प्रथम पत्ता 2 ने कमी केला जातो (0x0A00 - 2 = 0x09FE) आणि डेटा प्राप्त झालेल्या पत्त्यासह सेलवर लिहिला जातो.

मेमरी मूळतः यासारखी दिसत होती:

पुश कमांड कार्यान्वित केल्यानंतर (लाल रंगात हायलाइट केलेले बदल):

त्यामुळे डेटा रेकॉर्ड करण्यात आला आहे.
दोन ट्रान्सफर कमांड्स (mov) कार्यान्वित करून हे खरे आहे का ते तपासूया. प्रथम, आम्ही सेल 0x0A00 वरून डेटा प्राप्त करू आणि R5 नोंदणी करण्यासाठी लिहू, आणि नंतर R6 नोंदणी करण्यासाठी सेल 0x09FE वरून डेटा लिहू.
यानंतर, रजिस्टरमध्ये खालील डेटा असेल:

POP कमांड्स कार्यान्वित करताना, स्टॅकचा वरचा भाग प्रत्येक कमांडसह 2 ने वाढविला जाईल आणि R8-10 नोंदणीमधील डेटा अनुक्रमे 0x0000, 0x9250 आणि 0x0123 असेल.
जसजसा अधिक डेटा जोडला जाईल, तसतसे मेमरी (ज्यात अजूनही स्टॅकमधून पॉप केलेला डेटा आहे) नवीन मूल्यांनी भरले जाईल.

तुम्ही यासारख्या स्टॅकसह कामाचे उदाहरण देऊ शकता (डावीकडून उजवीकडे):

सुरुवातीला, स्टॅकचा पत्ता 0x0A00 होता, 0000 PUSH कार्यान्वित केल्यावर, खाली असलेला सेल (0x09FE पत्त्यासह) स्टॅकचा शीर्ष बनला आणि त्यावर डेटा लिहिला गेला. प्रत्येक त्यानंतरच्या कमांडसह, शीर्ष मेमरीमध्ये खाली स्थित आहे.
POP कमांड कार्यान्वित करताना, चित्र उलट होते.

मी टिप्पण्यांमधील तुमच्या प्रश्नांची वाट पाहत आहे.



आम्ही वाचण्याची शिफारस करतो

वर