पुनरावृत्ति बनाम पुनरावृत्ति


109

क्या यह कहना सही है कि हर जगह पुनरावृत्ति का उपयोग किया जाता है एक forलूप का उपयोग किया जा सकता है? और अगर पुनरावृत्ति आमतौर पर धीमी है, तो forलूप पुनरावृत्ति पर इसका उपयोग करने का तकनीकी कारण क्या है ?

और अगर एक पुनरावृत्ति को forलूप में बदलना हमेशा संभव होता है, तो क्या ऐसा करने के लिए अंगूठे का एक नियम है?


3
recursionबनाम iteration? iteration = for loopमुझे लगता है।
gongzhitaao

4
टॉम मॉर्टेल के ब्लॉग में पुनरावर्ती कोड को पुनरावृति कोड में परिवर्तित करने पर चार उत्कृष्ट पोस्ट हैं: blog.moertel.com/tags/recursion.html
cjohnson318

जवाबों:


148

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

कुछ अनुकूलन, जैसे टेल कॉल ऑप्टिमाइज़ेशन , तेज़ी से पुनरावृत्ति करते हैं लेकिन हमेशा संभव नहीं होते हैं, और सभी भाषाओं में लागू नहीं होते हैं।

पुनरावृत्ति का उपयोग करने के मुख्य कारण हैं

  • जब यह समस्या के हमारे दृष्टिकोण की नकल करता है तो यह कई मामलों में अधिक सहज है
  • पेड़ों की तरह कुछ डेटा संरचनाएं पुनरावृत्ति का उपयोग कर पता लगाने के लिए आसान हैं (या किसी भी मामले में ढेर की आवश्यकता होगी)

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


10
इसे जोड़ने के लिए - पुनरावृत्ति में कमी के शब्द से निकटता से संबंधित है जो कई एल्गोरिदम में और सामान्य रूप से सीएस में एक केंद्रीय भूमिका निभाता है।
SomeWittyUsername

3
क्या आप कृपया मुझे एक उदाहरण प्रदान कर सकते हैं जहाँ पुनरावृत्ति कोड को अधिक बनाए रखता है? मेरे अनुभव में, यह हमेशा दूसरा तरीका है। धन्यवाद
Yeikel

@ वायकेल एक फ़ंक्शन लिखता f(n)है जो nth फाइबोनैचि संख्या देता है
मैट

54

क्या यह कहना सही है कि हर जगह पुनरावृत्ति का उपयोग एक लूप के लिए किया जा सकता है?

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

और अगर पुनरावृत्ति आमतौर पर धीमी है, तो इसका उपयोग करने का तकनीकी कारण क्या है?

यह "आमतौर पर धीमा" नहीं है: यह पुनरावृत्ति है जिसे गलत तरीके से लागू किया गया है जो धीमी है। शीर्ष पर, आधुनिक संकलक कुछ पुनरावृत्तियों को बिना पूछे भी छोरों में परिवर्तित करने में अच्छे हैं।

और अगर एक लूप को एक लूप में बदलना हमेशा संभव होता है, तो क्या ऐसा करने के लिए अंगूठे का एक नियम है?

एल्गोरिदम के लिए पुनरावृति कार्यक्रमों को सबसे अच्छी तरह से समझें जब इसे पुनरावर्ती समझाया जाए; एल्गोरिदम के लिए पुनरावर्ती कार्यक्रम सबसे अच्छा पुनरावर्ती समझाएं।

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


+ मैंने दिज्क्स्ट्रा के "डिसिप्लिन ऑफ़ प्रोग्रामिंग" से स्लेजहेमर सादृश्य उधार लिया।


7
स्टैक फ्रेम बनाने और इस तरह के कारण रिकर्सियन आमतौर पर अधिक महंगा (धीमी / अधिक मेमोरी) है। पर्याप्त रूप से जटिल समस्या के लिए सही ढंग से लागू किए जाने पर अंतर छोटा हो सकता है, लेकिन यह अभी भी अधिक महंगा है। पूंछ पुनरावृत्ति अनुकूलन जैसे संभावित अपवाद हैं।
बर्नहार्ड बार्कर

मैं हर मामले में पाश के लिए एक के बारे में निश्चित नहीं हूं । एक और अधिक जटिल पुनरावृत्ति पर विचार करें या एकल चर से अधिक के साथ एक पुनरावृत्ति
SomeWittyUsername

@dasblinkenlight किसी एक के लिए कई लूप कम करना सैद्धांतिक रूप से संभव हो सकता है, लेकिन इस बारे में निश्चित नहीं है।
SomeWittyUsername

@icepack हाँ, यह संभव है। यह सुंदर नहीं हो सकता है, लेकिन यह संभव है।
बर्नहार्ड बार्कर

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

28

सवाल :

और यदि पुनरावृत्ति आमतौर पर धीमी है, तो लूप पुनरावृत्ति के लिए इसका उपयोग करने का तकनीकी कारण क्या है?

उत्तर:

क्योंकि कुछ एल्गोरिदम में इसे हल करना मुश्किल है। पुनरावर्ती और पुनरावृत्त दोनों में गहराई-पहली खोज को हल करने का प्रयास करें। आपको यह विचार मिलेगा कि DFS को पुनरावृत्ति के साथ हल करना सरल है।

प्रयास करने के लिए एक और अच्छी बात: मर्ज को क्रमबद्ध रूप से लिखने का प्रयास करें। इसमें आपको काफी समय लगेगा।

सवाल :

क्या यह कहना सही है कि हर जगह पुनरावृत्ति का उपयोग एक लूप के लिए किया जा सकता है?

उत्तर:

हाँ। इस धागे का इसके लिए बहुत अच्छा जवाब है।

सवाल :

और अगर एक लूप को एक लूप में बदलना हमेशा संभव होता है, तो क्या ऐसा करने के लिए अंगूठे का एक नियम है?

उत्तर:

मुझ पर विश्वास करो। गहराई से पहली खोज को हल करने के लिए अपना स्वयं का संस्करण लिखने का प्रयास करें। आप देखेंगे कि कुछ समस्याओं को पुनरावृत्ति से हल करना आसान है।

संकेत: पुनरावृत्ति अच्छा है जब आप एक समस्या को हल कर रहे हैं जिसे विभाजित और तकनीक से हल किया जा सकता है ।


3
मैं एक आधिकारिक उत्तर प्रदान करने के प्रयास की सराहना करता हूं और मुझे यकीन है कि लेखक बुद्धिमान है, लेकिन "मुझ पर विश्वास" एक सार्थक प्रश्न का एक उपयोगी प्रतिक्रिया नहीं है जिसका उत्तर तुरंत स्पष्ट नहीं है। एक पुनरावृत्त गहराई-पहली खोज करने के लिए बहुत सरल एल्गोरिदम हैं। Pseudocode
Jdelman

3

धीमी होने के अलावा, पुनरावृत्ति भी स्टैक अतिप्रवाह त्रुटियों के आधार पर परिणाम कर सकती है कि यह कितनी गहराई तक जाती है।


3

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

उदाहरण के लिए, त्रिकोणीय अनुक्रम की nth त्रिकोणीय संख्या ज्ञात करने के लिए: 1 3 6 10 15… एक प्रोग्राम जो n थ्री त्रिकोणीय संख्या को खोजने के लिए पुनरावृत्त एल्गोरिथ्म का उपयोग करता है:

पुनरावृत्त एल्गोरिथ्म का उपयोग करना:

//Triangular.java
import java.util.*;
class Triangular {
   public static int iterativeTriangular(int n) {
      int sum = 0;
      for (int i = 1; i <= n; i ++)
         sum += i;
      return sum;
   }
   public static void main(String args[]) {
      Scanner stdin = new Scanner(System.in);
      System.out.print("Please enter a number: ");
      int n = stdin.nextInt();
      System.out.println("The " + n + "-th triangular number is: " + 
                            iterativeTriangular(n));
   }
}//enter code here

पुनरावर्ती एल्गोरिथ्म का उपयोग करना:

//Triangular.java
import java.util.*;
class Triangular {
   public static int recursiveTriangular(int n) {
      if (n == 1)
     return 1;  
      return recursiveTriangular(n-1) + n; 
   }

   public static void main(String args[]) {
      Scanner stdin = new Scanner(System.in);
      System.out.print("Please enter a number: ");
      int n = stdin.nextInt();
      System.out.println("The " + n + "-th triangular number is: " + 
                             recursiveTriangular(n)); 
   }
}

1

अधिकांश उत्तर ऐसा लगता है कि iterative= for loop। यदि आपका लूप अप्रतिबंधित है ( एक ला C, आप अपने लूप काउंटर के साथ जो चाहें कर सकते हैं), तो यह सही है। यदि यह एक वास्तविक for लूप है (जैसा कि पायथन या सबसे कार्यात्मक भाषाओं में कहा जाता है जहां आप मैन्युअल रूप से लूप काउंटर को संशोधित नहीं कर सकते हैं), तो यह सही नहीं है।

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

जो बहुत अधिक महत्वपूर्ण है वह यह है कि पुनरावर्ती और भयानक रूप से कार्यान्वित करने के लिए पुनरावृत्ति को लागू करने के लिए बहुत सारे कार्य बहुत आसान हैं (मैन्युअल रूप से आपके कॉल स्टैक की गणना नहीं होती है)।


1

हां, जैसा कि थानाक्रॉन तंदवस ने कहा है ,

जब आप एक समस्या को हल कर रहे हैं जिसे विभाजित और तकनीक से हल किया जा सकता है तो पुनरावृत्ति अच्छा है।

उदाहरण के लिए: हनोई के टावर

  1. N बढ़ते आकार में बजता है
  2. 3 डंडे
  3. खंभे पर रखे गए छल्ले 1 से शुरू होते हैं। गोल को छल्ले को हिलाना होता है ताकि वे पोल 3 पर ढेर हो जाएं ... लेकिन
    • एक समय में केवल एक रिंग को हिला सकते हैं।
    • छोटे के ऊपर बड़ी रिंग नहीं डाल सकते।
  4. Iterative समाधान "शक्तिशाली अभी तक बदसूरत" है; पुनरावर्ती समाधान "सुरुचिपूर्ण" है।

एक दिलचस्प उदाहरण। मुझे लगता है कि आप एमसी एर "द टावर्स ऑफ हनोई और बाइनरी न्यूमर्स" द्वारा पेपर जानते हैं। इसके अलावा 3brown1blue द्वारा एक शानदार वीडियो में इलाज किया गया।
एंड्रेस्टैंड

0

मुझे याद है मेरे कंप्यूटर विज्ञान के प्रोफेसर दिन में वापस कहते हैं कि सभी समस्याओं के पुनरावर्ती समाधान भी पुनरावृत्त समाधान होते हैं। वह कहते हैं कि एक पुनरावर्ती समाधान आमतौर पर धीमा होता है, लेकिन उनका उपयोग अक्सर तब किया जाता है जब वे पुनरावृत्ति समाधानों की तुलना में इसके बारे में तर्क करना और कोड करना आसान होते हैं।

हालांकि, अधिक उन्नत पुनरावर्ती समाधानों के मामले में, मुझे विश्वास नहीं है कि यह हमेशा एक साधारण forलूप का उपयोग करके उन्हें लागू करने में सक्षम होगा ।


एक पुनरावर्ती एल्गोरिदम को पुनरावृत्त एक (स्टैक का उपयोग करके) में परिवर्तित करना हमेशा संभव होता है। आप विशेष रूप से सरल लूप के साथ समाप्त नहीं हो सकते हैं, लेकिन यह संभव है।
बर्नहार्ड बार्कर

-4

पुनरावृत्ति + संस्मरण एक शुद्ध पुनरावृत्त दृष्टिकोण के साथ तुलना में अधिक कुशल समाधान का नेतृत्व कर सकता है, उदाहरण के लिए यह जांच करें: http://jsperf.com/fibnote-memoized-vs-iterative-for-large-n


3
किसी भी पुनरावर्ती कोड को स्टैक का उपयोग करके कार्यात्मक समान पुनरावृत्ति कोड में परिवर्तित किया जा सकता है। जो अंतर आप दिखा रहे हैं, वही समस्या को हल करने के लिए दो दृष्टिकोणों के बीच का अंतर है, न कि पुनरावृत्ति और पुनरावृत्ति के बीच का अंतर।
बर्नहार्ड बार्कर

-6

संक्षिप्त उत्तर: व्यापार बंद पुनरावृत्ति तेजी से होता है और लगभग सभी मामलों में लूप कम मेमोरी लेते हैं। हालांकि आमतौर पर लूप बदलने या इसे तेजी से चलाने के लिए पुनरावृत्ति के तरीके हैं

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