1. الوظائف العودية، في مصطلحات الشخص العادي، تعني أن الوظيفة نفسها تسمي نفسها ...
مثل: ن!=ن(ن-1)!
يمكنك تحديد الدالة f(n)=nf(n-1)
وf(n-1) هي دالة لهذا التعريف. . هذا هو العودية
2. لماذا نستخدم العودية: الغرض من العودية هو تبسيط تصميم البرنامج وجعل البرنامج أسهل في القراءة.
3. مساوئ التكرار: على الرغم من أن الوظائف غير التكرارية ذات كفاءة عالية، إلا أنها صعبة البرمجة ولها قابلية قراءة ضعيفة. عيب الوظائف العودية هو أنها تزيد من حمل النظام، وهذا يعني أنه في كل مرة يتم تكرارها، تشغل ذاكرة المكدس مساحة أكبر.
4. شروط التكرار: يجب أن يكون هناك بيان لإكمال المهمة، ويجب استيفاء متطلبات التكرار (التقليل وليس التباعد)
5. التقدم العودي:
1. استخدم العودية لحساب مضروب n:
التحليل: ن!=ن*(ن-1)*(ن-2)...*1
public int dReturn(int n){ if(n==1){ return 1 }else{ return n*dReturn(n-1);
2. استخدم الدالة العودية لحساب التراكم من 1 إلى n: 1+2+3+4+..+n
public int dReturn(int n){ if(n==1){ return 1 }else{ return n+dReturn(n-1);
3. مطلوب إخراج تسلسل: 1,1,2,3,5,8,11... (كل رقم هو مجموع الرقمين السابقين، ويلزم وجود دالة عودية)
استخدم عودية جافا لتمثيل دالة: F(n)=F(n-1)+F(n-2);F(0)=1;F(1)=1;
التحليل: X1=1 X2=1;
public int F(int n){ if(n==1){ return 1 }else if(n==2){ return 1 }else{ return F(n-1)+F(n-2); } }
4. تستخدم Java طريقة عودية لطباعة كل عنصر في مصفوفة أعداد صحيحة بشكل عكسي
public static void printAll(int Index,int[] arr){ System.out.println(arr[index]); if(index > 0){ printAll(--index,arr) } } public static void main(String [] args){ int[] arr={1,2,3,4,5};
5. الحل البرمجي: إذا كانت البقرة تلد بقرة كل عام ابتداء من السنة الرابعة بعد الولادة، فكم عدد البقر في السنة التاسعة؟
public static int الماشية(int n){ if(n<=0){ return 0}else if(n<=3){ return 1;else{ return الماشية(n-1)+cattle(n-3) } } public static void main(String[] args){ int n=10; System.out.println(n+"سيكون هناك إجمالي "+cattle(n)+"أبقار" });
ما هي مفاهيم العودية والعودية الخطية والعودية الذيلية؟
استدعاء الوظائف العودية في Java - العثور على مضروب الرقم
لا يتم أخذ الفائض بعين الاعتبار: بشكل عام يمكن حساب مضروب 69 فقط...
ملاحظة: مضروب 0 هو 0! =1
التمثيل العاملي لأي عدد طبيعي n أكبر من 1:
ن!=1×2×3×……×ن
أو ن!=ن×(ن-1)!
سيؤدي البحث عن مضروب 0 إلى ظهور آلة حاسبة على الإنترنت، وهو أمر مفيد جدًا! !
اختبار الحزمة;استيراد java.util.Scanner;public class DiGui {public static void main(String[] args) {// TODO طريقة الإنشاء التلقائي stubSystem.out.println("أدخل عددًا صحيحًا:");Scanner scan = new Scanner(System.in);int x = scan.nextInt();int result = digui(x);System.out.println(result);}// وظيفة متكررة public static int digui(int x){if(x <=0){return 1;}else{return x*digui(x-1);}}}
العودية: العملية أو الوظيفة لديها طريقة لتسمية نفسها بشكل مباشر أو غير مباشر في تعريفها أو وصفها، وعادةً ما تقوم بتحويل مشكلة كبيرة ومعقدة إلى مشكلة أصغر مشابهة للمشكلة الأصلية التي يجب حلها. توضح هذه الحالة بوضوح كيف يمكن للتكرار أن يحول مشكلة معقدة إلى مشكلة أصغر يجب حلها. وفيما يلي مثال صغير لتوضيح مبدأ العودية.
/*** @fileName Test.java* @description ؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟* @date2012-11-25* @time 17:30* @author wst*/public class Test { static int multiply( int n) { int Factorial; // ?? if ((n == 0)) { Factorial = n } else { Factorial = n * multiply(n - 1); } public static void main(String[] args) { System.out.println(multiply(5) }}
عند استدعاء دالة، يتم إنشاء مساحة لمتغيراتها في مكدس وقت التشغيل. تظل متغيرات الدالة التي تم استدعاؤها مسبقًا موجودة في المكدس، ولكنها محجوبة بواسطة متغيرات الدالة الجديدة وبالتالي لا يمكن الوصول إليها.
تحتوي الدالة في البرنامج على متغيرين: المعلمة n والمتغير المحلي المضروب. توضح الرسوم البيانية التالية حالة المكدس، مع وجود المتغيرات التي يمكن الوصول إليها حاليًا في الأعلى. جميع المتغيرات الأخرى التي يتم استدعاؤها مظللة باللون الرمادي للإشارة إلى أنه لا يمكن الوصول إليها بواسطة الوظيفة المنفذة حاليًا.
لنفترض أننا نسمي الدالة العودية بالقيمة 5. محتويات المكدس هي كما يلي، مع الجزء العلوي من المكدس في الأسفل:
n ضرب (n) مضروب 5 ضرب (5) 5 * ضرب (4) // الاتصال الأول 4 ضرب (4) 4 * ضرب (3) // الاتصال الثاني 3 ضرب (3) 3 * ضرب (2) // النداء الثالث 2 ضرب (2) 2 * ضرب (1) // النداء الرابع 1 ضرب (1) 1 // النداء الخامس
من المعلومات المذكورة أعلاه، يمكن أن نرى بسهولة كيف أن التكرار يقلل المشكلة تدريجيًا لحلها، بدءًا من استدعاء الطريقة، سيتم دفع نتائج العوامل إلى المكدس حتى انتهاء استدعاء الطريقة، وفي النهاية يتم إرجاع النتائج واحدة تلو الأخرى. من أعلى المكدس. وبعد الاستبدال واحدا تلو الآخر تكون النتيجة كما يلي:
n=1 1 يُرجع 1 لأعلى
n=2 2*multiply(1) يُرجع 2*1=2 لأعلى
n=3 3*multiply(2) يُرجع 3*(2*1)=6 لأعلى
n=4 4*ضرب(3) يُرجع 4*(3*(2*1))=24 لأعلى
n=5 5*multiply(4) ترجع لأعلى 5*(4*(3*(2*1))=120
ملاحظة: لأن الضرب (1) أو الضرب (0) يُرجع قيمة 1
إذن هناك 2*ضرب(1)=2*1=2
ولأن الضرب (2) يفي بشرط العودية، فيمكن تحويله إلى 2*ضرب(1) بعد العودية.
إذن هناك 3*ضرب(2)=3*(2*ضرب(1))=3*(2*1)=6
لأنه يمكن تقليل الضرب (3) إلى 3 * الضرب (2) بعد العودية
لذا اضرب(4)=4*اضرب(3)=4*(3*اضرب(2))=4*(3*(2*1))=24
بالقياس، اضرب(5)=5*اضرب(4)
يمكن اختزالها إلى 5*(4*مضاعفة(3))=5*(4*3*(مضاعفة(2)))=5*(4*(3*(2*1))=120
دعونا نلقي نظرة على معلومات الرمز الثانوي:
public class Test Extends java.lang.Object{ public Test(); (int); Code: 0: iload_0 1: Iconst_1 // ادفع ثابت النوع int 1 إلى المكدس 2: if_icmpeq 9 // قارن بين قيمتين من النوع int، إذا كانتا متساويتين، فانتقل إلى الموضع 9، وهذا هو || الوظيفة 5: iload_0 // يتم تنفيذ هذا عندما لا يتم الاحتفاظ بالشرط الأول، ويتم تحميل قيمة النوع int من المتغير المحلي 0 (ادفع قيمة n إلى المكدس) 6: ifne 14 // قارن، إن لم يكن إذا كان يساوي 0 ، انتقل إلى الموضع 14. ملاحظة: نظرًا لأن المقارنة الافتراضية هنا هي 0، ليست هناك حاجة لدفع الثابت 0 إلى المكدس 9: iload_0 // إذا لم يكن هناك قفزة عند ifne، فقم بتحميل int من المتغير المحلي 0 اكتب القيمة (ادفع قيمة n إلى المكدس) 10: istore_1 // قم بتخزين قيمة النوع int في المتغير المحلي 1 (القيمة المنبثقة من أعلى المكدس هي القيمة التي تم دفعها إلى المكدس بواسطة المتغير المحلي 0، ثم تخزينها في المتغير المحلي 1) 11: goto 23 // انتقال غير مشروط إلى الموضع 23 14: iload_0 // المقارنة في الموضع 6، إذا لم تكن تساوي 0، قم بتنفيذ هذه التعليمات، وتحميل قيمة النوع int من المتغير المحلي 0 (ادفع قيمة n على المكدس) 15 : iload_0 // قم بتحميل قيمة النوع int من المتغير المحلي 0 (ادفع قيمة n إلى المكدس) 16: Iconst_1 // ادفع ثابت النوع int 1 إلى المكدس، الثابت 1 هو 1 من n -1 في الكود 17: isub // تنفيذ عملية الطرح، n-1 18: invocstatic #2; // طريقة الضرب:(I)I، طريقة الاتصال تتضاعف 21: imul // تنفيذ عملية الضرب، n * multiply(n) - 1) 22: istore_1 // هل سيتم تخزين قيمة النوع int في المتغير المحلي 1، العامل =... 23: iload_1 // قم بتحميل قيمة النوع int من المتغير المحلي 1 (ادفع نتيجة العامل إلى المكدس) 24 : ireturn // تُرجع الطريقة public static void main( java.lang.String[]); : invocatic #2; // طريقة الضرب:(I)I 7: invocationvirtual #4; //Method java/io/PrintStream.println:(I)V 10: return }