الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

استقسار في الاستدعاء الذاتي

مغلق
بدأه ibr_exn في 22 يوليو 2006 · 10 رد · 2,293 مشاهدة · في الرياضيات والخوارزميات
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته

من المواضيع المهمة في البرمجة و الخوارزميات موضوع التعاودية recursion

المشكلة اني رغم اني خريج علوم حاسوب بس الى الان اجد صعوبة في حل مسائله

هل من درس يبسط هذا الموضوع ؟

مثلا حاولت احول هذه الخوارزمية الى تعاودية ولم اقدر

عمل عدد من التكرارات

في حالة تكرارين

for i:=1 to 2 do

for j:=1 to 2 do

writeln(i,j);

في حالة 3 تكرارات

for i:=1 to 3 do

for j:=1 to 3 do

for k:=1 to 3 do

writeln(i,j,k);

لاحظوا معي ان عدد التكرار متغير حسب عدد المتغيرات

كيف يمكن عمل برنامج ديناميكي بحيث ندخل عدد المتغيرات وهو يعمل التكرار حسب لمطلوب

ارجو شرح الفكرة ان امكن

تحياتي للجميع

الحمد لله الذي هدانا لهذا وماكنا لنهتدي لولا ان هدانا الله

#2

السلام عليكم

بدون فهم لوظيفة المكدس لن تفهم الاستدعاء الذاتي لذلك انصحك ان تتعمق فى فهم كيفية عمل المكدس اولاً..

بالنسبة لتحويل اكثر من loop ليصبح إستدعاء تعاودي يجب عليك ان تحول كل loop لدالة منفصلة, لان التعاودية هى عملية loop باستخدام دالة ...

طبعاً كل loop خارجي يتوقع منه ان يستخدم نتائج الloop الداخلي لذلك يجب ان تستدعى الloop الخارجي والذى قمنا بتحويلة إلى دالة تجعله يستدعي الloop الخارجي والذى هو فى دالة منفصلة, ومن ثم تقوم بعملية الاستدعاء الذاتي مرة اخرى ...

مشكلة الاستدعاء الذاتي هى انها تستهلك الذاكرة بشكل كبير جداً لذلك لا انصح ابداً بإستخدامها فى البرمجة, يمكنك ان تستخدمها لفهم الية المكدس فقط, اما للبرامج فيمكنك ان تستعيض بإستخدام loop او wihle الخ لان هذا النوع من الحلقات لا يستهلك الذاكرة...

والسلام عليكم

لا إله إلا الله محمد رسول الله

busbar : يجب ان تدرك انه هناك حد ادنى للمعرفة المطلوبة قبل البدء في عمل أي شئ.

#3
احمد غريب كتب:
مشكلة الاستدعاء الذاتي هى انها تستهلك الذاكرة بشكل كبير جداً لذلك لا انصح ابداً بإستخدامها فى البرمجة, يمكنك ان تستخدمها لفهم الية المكدس فقط, اما للبرامج فيمكنك ان تستعيض بإستخدام loop او wihle الخ لان هذا النوع من الحلقات لا يستهلك الذاكرة...

والسلام عليكم

صحيح مثل ما قال أخوي أحمد لكن يبقى للإستدعاء الذاتي ميزته في بساظته من ناحية القراءه او من ناحية الفهم ;)

لكنه سيكون على حساب السرعة والذاكرة

تم تعديل هذه المشاركة بواسطة b.m.s في 23 يوليو 2006 في 12:43

#4

مشكورين على الايضاح

ولكن اعتقد انه توجد حالات لايمكن ان يفيد معها سوى الاستدعاء الذاتي

الاخ احمد اذا كان لكل تكرار دالة تعاودية فاين ستكون الديناميكية في البرنامج

واذا كان يحتل بدون تعاودية الرجاء ايضاح الطريقة

تحياتي للجميع

الحمد لله الذي هدانا لهذا وماكنا لنهتدي لولا ان هدانا الله

#5

السلام عليكم

كل ما تفعله فى الاستدعاء الذاتي تستطيع ان تقوم به فى حلقة, لان الاستدعاء الذاتي ماهو سوى حفظ المتغيرات فى المكدس وإستدعاء الدالة, حفظ المتغيرات فى المكدس وإستدعاء الدالة ....... وهكذا, وعندما تنتهى من الاستدعاء الذاتي تقوم بإسترجاع محتوى المكدس لكل حالة إستدعاء قمت بها حتى تفرغ المكدس من جميع الدوال التى احتفظت بها فيه...

مثال بسيط

int y=0;
int sum(int x){
if(x!=0)
y=x+sum(x-1);
return y;
}

هذا المثال البسيط يقوم بالحصول على المتغير x ثم يقوم بجمع x لباقى الاعداد التى هى اقل من x ...

فى الواقع الذى يحدث هو ان البرنامج عندما يكتشف ان هناك إستدعاء لدالة سواً كان استدعاء ذاتي او غير ذاتى يقوم بحفظ المتغيرات فى المكدس قبل ان يقوم بعلية الجمع...

لنفرض ان x تساوى 3 حتى لا تطول المسئلة ..

فى الخطوة الاولى سيكتشف البرنامج ان هناك استدعاء ذاتي فسيقوم بحفظ العدد 3 فى المكدس... ويقوم بستدعاء الدالة استدعاء ذاتي وهذه المرة قسمة التمتغير هى 2..

الدالة تكتشف ان x اكبر نم صفر وان هناك استدعاء ذاتي, فتقوم بحفظ العدد 2 فى المكدس وتستدعى الدالة بالعدد 1 , وهنا يحدث نفس الشيئ ويحفظ العدد 1 فى المكدس..

واخيراً تكتشف الدالة ان العدد اصبح صفر فتقوم بعملية return للعدد 0.

return تعني انك تعود لنفس المكان الذى تركت فى الدالة لذلك ستعود للسطر الذى يجمع العدد x و العدد الذى هو جمع x-1 , ولكن الان لدينا اعداد حقيقية وليس استدعاء ذاتي لان return اعادت لنا العدد 0, واخر عدد احتفظنا به فى المكدس هو العدد 1 إذاً y تصبح 0+1 ثم نقوم بعملية اعادة return للعدد 1 ونعد إلى نفس السطر الذى تركنا التنفيذ منه وهو نفس السطر الذى يجمع الاعداد... الان معنا العدد 1 وفى المكدس هناك العدد 2 إذا عملية الجمع ستنفذ على العددين 1 و 2 والمجموع هو 3 ثم نقوم بعلية return والتى تعيد العدد 3 واخيراً لدينا العدد 3 فى المكدس نجمعها فى نفس السطر فتصبح القيمة 6 ثم نقوم بعملية return للعدد 6 ولكن هذه المرة لا نعود إلى نفس السطر وإنما نذهب بالقيمة للسطر الذى قام بإستدعاء الدالة فى بداية العملية الحسابية...

كما تلاحظ العملية ماهى إلا عملية loop سهلة فى شكلها معقدة فى ادائها وفهمها, وكما تلاحظ ايضاً يمكن عمل نفس الالية بloop عادي ....

ارجو ان تكون الفكرة قد اتضحت...

والسلام عليكم

لا إله إلا الله محمد رسول الله

busbar : يجب ان تدرك انه هناك حد ادنى للمعرفة المطلوبة قبل البدء في عمل أي شئ.

#6

الف شكر واسف يا اخي لاني غلبتك معاي

هل ممكن حل المسألة التي طرحتها في اول مشاركة و هي تغيير عدد التكرارات حسب عدد المتغيرات

سواء بتكرار او بدون لاني لا اظن انها تحتل بدون تعاودية

الف شكر

الحمد لله الذي هدانا لهذا وماكنا لنهتدي لولا ان هدانا الله

#7

اعتقد ان افضل طريقة لحل مثل هذه المسئلة هو بإرسال المتغيرات على شكل سلسلة array لانه على حسب ما وضحت فى سؤالك فانت لا تعرف مسبقاً عدد المتغيرات...

او يمكنك ان ترسل مؤاشر يحتوى على عنوان تحفظ فيه المتغيرات ومتغير يحدد عدد المتغيرات التى تريد استخدامها...

وإن شاء الله لو جائت لي فكرة افضل اطرحها, ولكن حالياً الوقت متاخر عندى ...

والسلام عليكم

لا إله إلا الله محمد رسول الله

busbar : يجب ان تدرك انه هناك حد ادنى للمعرفة المطلوبة قبل البدء في عمل أي شئ.

#8

شوف الدالة دى كدا >

void rep(const int n, vector<int>& prev)
{
	if (n - prev.size() == 1) // we reached the deepest level
	{
		for (int i=1; i<=n; i++)
		{
			disp(prev); // function to display a vector
			cout << i << endl;
		}
		return;
	}
	for (int i=1; i<=n; i++)
	{
		prev.push_back(i);
		rep(n, prev);
		prev.pop_back();
	}
}
#10

شكله واجب منزلي ولكن:

package test;
public class Recursion{
	static int count=0;
	private static void specialPrint(int loop, int counter, String text){
		for(int i=0;i<loop;i++){
			if(counter>1)specialPrint(loop, counter-1, text);
			if(counter==1)System.out.println(text);
		}
	}
	public static void specialPrint(int loop, String text){
		specialPrint(loop, loop, text);
	}
	public static void main(String[]args){
		System.out.println("3^3 test: ");
		specialPrint(3,"La ilaha Illa Allah");
		System.out.println("-----------------");
		count=0;
		System.out.println("2^2 test: ");
		specialPrint(2,"La ilaha Illa Allah");
		System.out.println("-----------------");
		count=0;

	}
}

الناتج:

3^3 test:
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
-----------------
2^2 test:
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
La ilaha Illa Allah
-----------------
Press any key to continue...
#11

مشكور على المشاركة

يا عم الموضوع لا واجب منزلي ولا حاجة اصل انا تخرجت من زمان

المشكلة انه الى الان هذه الخوارزميات مش عارف احلها وكان عندي حلقة مفقودة في اللي تعلمته

اذا امكن هل ممكن بعض الشرح

تحياتي

الحمد لله الذي هدانا لهذا وماكنا لنهتدي لولا ان هدانا الله

هذا الموضوع مغلق.

مواضيع مشابهة