
المشاركة الأصلية كتبت بواسطة ThE* DaRk *SiDe
السلام عليكم ورحمة الله وبركاته
يوجد لدي لبس في أحد الامثلة في موضوع العودية:
في المثال الأول في الأمثلة التطبيقية لدرس الخامس ،أنا فهمت العودية لكن المشكلة في هذا المثال أنني حينما
أحوال أن أستنتج الحل بنفسي يكون الحل غير الحل الصحيح.
في هذا المثال لو فرضنا أننا أدخلنا 4قوة3 يكون الناتج كما في الصورة المرفقة
http://www.montada.com/attachment.ph...d=200409&stc=1
لكن النتج الصحيح هو 64.
هل من الممكن أخي أن تشرح لي كيف يستنتج البرنامج الحل الصحيح ؟
وشكرا.......
أخي الكريم ..
بالنسبة لهذا المثال .. كان التابع ( power ) مكتوباً على الشكل التالي :
كود:
int power(int x, int y)
{
if( y==0 ) return 1;
else return( x*power(x, y-1) );
}
و مع افتراض أننا نريد حساب 4 قوة 3 .. و بذلك سيكون استنتاج الحل كالتالي :
في الاستدعاء الأول ( حيث أن main قام باستدعاء هذا التابع ) :
قيمة x : ثابتة دائماً في جميع الاستدعاءات و تساوي 4 .
قيمة y : في هذا الاستدعاء تساوي 3 .
و بما أن ( y ) لا تساوي الصفر .. فسيتم تنفيذ التعليمة التالية :
كود:
return( x*power(x, y-1) );
لاحظ هنا كيف أننا سنعيد للتابع main ناتج ضرب : 4 × 4 قوة 2 .. و هي تساوي ( 4 قوة 3 ) .. و لكن قبل أن نعيد ذلك الناتج علينا حساب 4 قوة 2 لذلك سيتم استدعاء التابع ( power ) مرة أخرى من أجل تلك العملية .
القيمة المعادة للتابع main : غير معروفة إلى أن يتم معرفة قيمة 4 قوة 2 .. و عند الحصول على القيمة ( 4 قوة 2 ) من الاستدعاء الثاني نعيد للتابع main الناتج ( 4 × 4 قوة 2 ) و هو يساوي ( 4 قوة 3 ) .
في الاستدعاء الثاني :
قيمة x : قلنا أنها ثابتة دائماً في جميع الاستدعاءات و تساوي 4 .
قيمة y : في هذا الاستدعاء تساوي 2 .. لأن الاستدعاء الأول قام بإرسال ( y-1 ) .
و بما أن ( y ) لا تساوي الصفر .. فسيتم تنفيذ التعليمة التالية :
كود:
return( x*power(x, y-1) );
إذا هنا سيتم حساب ( 4 قوة 2 ) و إعطاء ذلك الناتج للاستدعاء الأول .. و لكننا سنحسب تلك العملية عن طريق ( 4 × 4 قوة 1 ) و هي تساوي ( 4 قوة 2 ) .. لذلك سيتم إرسال ( 4 قوة 1 ) للاستدعاء الثالث لكي يتم حسابها .
القيمة المعادة للاستدعاء الأول : غير معروفة أيضاً إلى أن يتم حساب ( 4 قوة 1 ) في الاستدعاء الثالث .. و عند الحصول على ذلك الناتج سيتم إرجاع ( 4 × 4 قوة 1 ) للاستدعاء الأول .
في الاستدعاء الثالث :
قيمة x : أيضاً تساوي 4 .
قيمة y : في هذا الاستدعاء تساوي 1 .. لأن الاستدعاء الثاني قام بإرسال ( y-1 ) .
و بما أن ( y ) لا تساوي الصفر .. فسيتم تنفيذ التعليمة التالية :
كود:
return( x*power(x, y-1) );
هنا ( في هذا الاستدعاء ) سيتم حساب ( 4 × 4 قوة 0 ) و هي تسوي ( 4 قوة 1 ) .. و سيتم إرسال هذا الناتج كقيمة معادة إلى الاستدعاء الثاني .. و لكن قبل ذلك علينا حساب ( 4 قوة 0 ) و هذا ما سوف ينفذه الاستدعاء الرابع .
القيمة المعادة للاستدعاء الثاني : غير معروفة أيضاً إلى أن يتم حساب ( 4 قوة 0 ) و عندها سيتم إرجاع القيمة ( 4 × 4 قوة 0 ) للاستدعاء الثاني .
في الاستدعاء الرابع :
قيمة x : أيضاً تساوي 4 .
قيمة y : هنا نكون قد وصلنا إلى الحالة النهائية و هيا الحالة المعروفة جوابها و هي عندما يكون الأس يساوي ( الصفر ) .. لذلك سيتم تنفيذ التعليمة التالية :
هنا ستكون القيمة المعادة للاستدعاء الثالث تساوي واحد و هي ناتج ( 4 قوة 0 ) .. و بذلك سيتم إرجاع القيم بالتسلسل بين الاستدعاءات حتى الرجوع إلى التابع main .. و ذلك كالتالي :
الاستدعاء الرابع سيعيد القيمة ( 1 ) للاستدعاء الثالث .. و الاستدعاء الثالث سيعيد القيمة ( 4 × 4 قوة 0 ) إلى الاستدعاء الثاني ( الناتج إلى الأن 4 ) .. و الاستدعاء الثاني سيعيد القيمة ( 4 × 4 قوة 1 ) إلى الاستدعاء الأول ( الناتج 16 ) .. و أخيراً الاستدعاء الأول سيعيد القيمة ( 4 × 4 قوة 2 ) إلى التابع الرئيسي main و سيكون الناتج ( 64 ) .
أتمنى أن تكون الفكرة قد وصلت .. بالتوفيق .
:: تنبيه ::
هناك أخطاء جوهري و منطقية في الدرس الثامن في فقرة ( التحرير الديناميكي ) .. لذلك لا تأخذوا بما هو مكتوب في تلك الفقرة .. و سيتم التصحيح قريباً إن شاء الله ( بمساعدة المراقب ) .. و الخطأ كان مني لعدم تأكدي من المعلومات التي كتبتها .. وسيتم توضيح أنه تم تصحيح تلك المعلومات داخل تلك الفقرة .
لذلك أرجو الانتباه إلى من يقوم بتصوير هذه الدروس و نشرها في الجامعات على هذا الخطأ لأني على علم بذلك .. و جزاهم الله خيراً على عملهم و حرصهم .. و الله الموفق .