📘 CodingMarble Learn

रिकर्शन: ख़ुद को पुकारने वाले फ़ंक्शन

रिकर्शन (recursion) तब होता है जब कोई फ़ंक्शन किसी प्रश्न को हल करने के लिए उसी प्रश्न के छोटे रूप पर ख़ुद को पुकारता है। हर रिकर्सिव फ़ंक्शन में एक आधार स्थिति (base case) चाहिए, जहाँ वह रुककर सीधे उत्तर देता है, और एक रिकर्सिव स्थिति जो आधार स्थिति की ओर बढ़ती है। हर पुकार को कॉल स्टैक पर अपना स्टैक फ़्रेम मिलता है; पुकार लौटने पर फ़्रेम हट जाता है।

🎬 कदम-दर-कदम कहानी

  1. fact(4) का मतलब है 4 × 3 × 2 × 1। अंदर देखिए: fact(4) बस 4 × fact(3) है। और fact(3) है 3 × fact(2)। हर डिब्बे में उसी प्रश्न की छोटी कॉपी है।
  2. सबसे छोटा डिब्बा fact(1) है। इसका उत्तर सीधे 1 है। यह आधार स्थिति है। यहाँ फ़ंक्शन ख़ुद को पुकारना बंद कर देता है।
  3. प्रोग्राम चलने पर हर पुकार कॉल स्टैक पर एक नया फ़्रेम रखती है। मीनार बढ़ती है: fact(4), fact(3), fact(2), fact(1)।
  4. अब उत्तर नीचे लौटते हैं। fact(1) 1 लौटाता है। फिर 2 × 1 = 2, 3 × 2 = 6, 4 × 6 = 24। हर फ़्रेम उत्तर लौटाकर स्टैक से हट जाता है।
  5. अगर आधार स्थिति न हो तो? पुकारें कभी नहीं रुकतीं। फ़्रेम तब तक ढेर होते हैं जब तक मेमोरी ख़त्म न हो जाए। इस त्रुटि को स्टैक ओवरफ़्लो कहते हैं।
  6. अब आपकी बारी। कोई संख्या n चुनिए और ▶ दबाइए। फ़्रेम ऊपर चढ़ते और उत्तर लेकर नीचे उतरते देखिए।

टिप: 3D दृश्य को घुमाने के लिए खींचें। ज़ूम के लिए दो उंगलियाँ इस्तेमाल करें।

🤔 आम शंकाएँ और उनके जवाब

फ़ंक्शन ख़त्म होने से पहले ख़ुद को कैसे पुकार सकता है?

हर पुकार अपने n के साथ एक अलग कॉपी है। fact(4) पंक्ति fact(3) पर रुकता है और नई कॉपी शुरू होती है। चरण 1 में डिब्बों के अंदर डिब्बे देखिए।

आधार स्थिति क्यों चाहिए?

यह वह इनपुट है जो इतना छोटा है कि बिना फिर पुकारे उत्तर मिल जाए। इसके बिना पुकारें कभी नहीं रुकतीं। चरण 2 में आधार वाला डिब्बा चमकता है।

fact(3) चलते समय n = 4 कहाँ रखा रहता है?

fact(4) के अपने स्टैक फ़्रेम में, जो स्टैक पर इंतज़ार करता है। हर फ़्रेम अपना n रखता है। चरण 3 की मीनार देखिए।

गुणा असल में कब होता है?

लौटते समय। fact(4) 4 × fact(3) तभी कर सकता है जब fact(3) ने 6 लौटा दिया हो। चरण 4 में हर फ़्रेम हटते समय गुणनफल दिखता है।

स्टैक ओवरफ़्लो क्या है?

स्टैक की मेमोरी सीमित है। पुकारें आधार स्थिति तक न पहुँचें तो फ़्रेम ढेर होते जाते हैं, जगह ख़त्म होती है और प्रोग्राम रुक जाता है। चरण 5 देखिए।

क्या रिकर्शन लूप से धीमा है?

अक्सर थोड़ा, क्योंकि हर पुकार एक फ़्रेम जोड़ती है। fact(n) में स्टैक n फ़्रेम ऊँचा होता है; खुले खेल में n = 7 पर ▶ दबाकर देखिए। लूप एक ही फ़्रेम में चलता है।

रिकर्शन क्या है?

फ़ंक्शन कोड का एक नाम वाला हिस्सा है जो एक काम करता है। आम तौर पर यह दूसरे फ़ंक्शनों को पुकारता है।

रिकर्सिव फ़ंक्शन ख़ुद को पुकारता है। यह बड़े प्रश्न को हल करने के लिए पहले उसी प्रश्न की छोटी कॉपी हल करता है।

उदाहरण: फ़ैक्टोरियल n! = n × (n − 1) × … × 1। ध्यान दीजिए 5! = 5 × 4!। तो fact(5) के लिए fact(4) निकालकर 5 से गुणा कीजिए।

def fact(n):
    if n == 1:          # आधार स्थिति
        return 1
    return n * fact(n - 1)   # रिकर्सिव स्थिति

आधार स्थिति और रिकर्सिव स्थिति

हर सही रिकर्सिव फ़ंक्शन के दो हिस्से होते हैं:

कोई भी हिस्सा ग़लत हो तो फ़ंक्शन कभी नहीं रुकता। जैसे आधार स्थिति के बिना fact(n − 1), या fact(n + 1) जो उससे दूर जाता है।

कॉल स्टैक और स्टैक फ़्रेम

कंप्यूटर अधूरी पुकारों का हिसाब कॉल स्टैक से रखता है। स्टैक थालियों के ढेर जैसा है: जो आख़िर में रखी, वही पहले उठेगी (LIFO)।

हर पुकार को एक स्टैक फ़्रेम मिलता है। इसमें उसके पैरामीटर (जैसे n), स्थानीय चर और रिटर्न पता (ख़त्म होने के बाद कहाँ लौटना है) रहते हैं।

  1. fact(4) शुरू होता है और fact(3) का इंतज़ार करता है। उसका फ़्रेम स्टैक पर रहता है।
  2. fact(3), fact(2) का और fact(2), fact(1) का इंतज़ार करता है।
  3. fact(1) आधार स्थिति पर 1 लौटाता है। उसका फ़्रेम हट जाता है।
  4. अब हर इंतज़ार करता फ़्रेम अपना गुणा पूरा करके बारी-बारी हटता है।

बहुत सारे फ़्रेम स्टैक की मेमोरी भर देते हैं। प्रोग्राम स्टैक ओवरफ़्लो से रुक जाता है (Python में RecursionError)।

रिकर्सिव फ़ंक्शन को ट्रेस करना

ट्रेस करने के लिए हर पुकार नई पंक्ति में, एक स्तर अंदर खिसकाकर लिखिए। पुकार लौटे तो उसका मान लिखकर ऊपर लौटिए।

power(2, 3)
  power(2, 2)
    power(2, 1)
      power(2, 0) returns 1
    returns 2 × 1 = 2
  returns 2 × 2 = 4
returns 2 × 4 = 8

जो फ़ंक्शन ख़ुद को दो बार पुकारे, जैसे फ़िबोनाची fib(n) = fib(n − 1) + fib(n − 2), वह पुकारों का पेड़ बनाता है। fib(5) में fib(3) दो बार और fib(2) तीन बार बनता है, यानी बहुत काम दोहराया जाता है। पहले से निकाले उत्तर सँभालकर रखना (मेमोइज़ेशन) इसे ठीक करता है।

रिकर्सिव खोज और छँटाई

बाइनरी सर्च (क्रमबद्ध सूची में): बीच वाला आइटम देखिए। वही लक्ष्य हो तो रुकिए (आधार स्थिति)। लक्ष्य छोटा हो तो बाएँ आधे में, बड़ा हो तो दाएँ आधे में खोजिए। ख़ाली सीमा दूसरी आधार स्थिति है (नहीं मिला)। हर पुकार सूची आधी करती है, तो 1 000 आइटमों के लिए लगभग 10 पुकारें काफ़ी हैं।

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

रिकर्शन या लूप?

रिकर्शन से होने वाला हर काम लूप (इटरेशन) से भी हो सकता है, और उल्टा भी।

कुछ भाषाएँ (फ़ंक्शनल भाषाएँ) दोहराने के लिए मुख्य रूप से रिकर्शन ही उपयोग करती हैं।

करके देखिए: कक्षा की क़तार

क़तार के आख़िरी विद्यार्थी से पूछिए: "तुम्हारे आगे कितने लोग हैं?" वह गिनता नहीं। वह आगे वाले से यही प्रश्न पूछता है और उत्तर में 1 जोड़ता है। क़तार में पहले विद्यार्थी के आगे कोई नहीं, वह 0 कहता है (आधार स्थिति)। उत्तर पीछे लौटते आते हैं। फिर Python में fact(n) लिखकर n = 5 पर चलाइए और 3D के चरण 4 से मिलाइए।

मुख्य सूत्र और परिभाषाएँ

हल किए गए उदाहरण

1. 1 से n तक की संख्याएँ जोड़ने वाला रिकर्सिव फ़ंक्शन लिखिए।

आधार स्थिति: n = 0 → 0 लौटाओ। रिकर्सिव स्थिति: n + total(n − 1) लौटाओ। <pre>def total(n): if n == 0: return 0 return n + total(n - 1)</pre>total(4) = 4 + 3 + 2 + 1 + 0 = 10।

2. fact(3) ट्रेस कीजिए और स्टैक दिखाइए।

पुकारें: fact(3) → fact(2) → fact(1)। सबसे ऊँचा स्टैक: fact(3) के ऊपर fact(2), उसके ऊपर fact(1)। लौटना: fact(1) = 1, fact(2) = 2 × 1 = 2, fact(3) = 3 × 2 = 6।

3. इसमें क्या ग़लत है: def f(n): return n * f(n - 1)

आधार स्थिति नहीं है। f(3) → f(2), f(1), f(0), f(−1)… बिना रुके। Python इसे RecursionError (स्टैक ओवरफ़्लो) से रोकता है। जोड़िए: if n <= 1: return 1।

4. स्ट्रिंग उल्टी करने वाला रिकर्सिव फ़ंक्शन लिखिए।

आधार स्थिति: ख़ाली स्ट्रिंग वैसी ही लौटे। वरना आख़िरी अक्षर + बाक़ी का उल्टा। <pre>def rev(s): if s == "": return "" return s[-1] + rev(s[:-1])</pre>rev("cat") = "t" + rev("ca") = "t" + "a" + rev("c") = "tac"।

5. सादे रिकर्शन में fib(4) कुल कितनी पुकारें करता है?

fib(4) → fib(3), fib(2)। fib(3) → fib(2), fib(1)। हर fib(2) → fib(1), fib(0)। गिनती: fib(4) 1, fib(3) 1, fib(2) 2, fib(1) 3, fib(0) 2 = 9 पुकारें।

6. [3, 8, 15, 23, 42, 57, 61] में 57 को बाइनरी सर्च से खोजिए।

पुकार 1: बीच में 23 (इंडेक्स 3); 23 < 57 → दायाँ आधा [42, 57, 61]। पुकार 2: बीच में 57 → मिल गया। 2 पुकारें।

आम गलतियाँ

अभ्यास क्विज़

1. रिकर्सिव फ़ंक्शन वह है जो:
2. रिकर्सिव फ़ंक्शन का वह हिस्सा जो पुकारें रोकता है:
3. हर पुकार कॉल स्टैक पर किस रूप में रखी जाती है?
4. fact(n) = n × fact(n − 1), fact(1) = 1 से fact(5) =
5. बिना आधार स्थिति वाला रिकर्शन आम तौर पर किस पर ख़त्म होता है?

अभ्यास: खुद जवाब दो

अपना जवाब लिखो या चुनो, फिर जाँचें दबाओ। अटको तो संकेत देखो; जवाब देने के बाद पूरा हल दिखेगा।

अक्सर पूछे जाने वाले प्रश्न

रिकर्शन आसान शब्दों में क्या है?

जब कोई फ़ंक्शन किसी प्रश्न को उसी प्रश्न के छोटे रूप पर ख़ुद को पुकारकर हल करता है, जब तक इतना सरल रूप न आ जाए जिसका उत्तर सीधे पता हो।

रिकर्शन में आधार स्थिति क्या है?

रुकने की शर्त: सबसे सरल इनपुट, जिसका उत्तर फ़ंक्शन ख़ुद को फिर पुकारे बिना लौटाता है।

क्या रिकर्शन इटरेशन से बेहतर है?

कोई हमेशा बेहतर नहीं। पेड़ और मर्ज सॉर्ट जैसे प्रश्नों में रिकर्शन साफ़ है; लूप कम मेमोरी लेता है और स्टैक ओवरफ़्लो नहीं होता।

यह कहाँ पढ़ाया जाता है

रोमानियाClasa a XI-aSubprograms
यूक्रेन10 класProgramming language and data structures
इंग्लैंडYear 134.1 Fundamentals of programming (A-level)
अमेरिकाGrade 11Data Collections
अमेरिकाGrade 11Algorithms and Programming
जर्मनीJahrgangsstufe 12Recursion
फ्रांसTerminaleLanguages and programming
रूस9 классAlgorithms and programming

पहले यह पढ़ें

आगे पढ़ें

इससे जुड़े पाठ

सभी कंप्यूटर विज्ञान पाठ