يمكن أن يحتوي الإجراء أو الوظيفة على استدعاء لإجراء آخر داخله. بما في ذلك ، يمكن للروتين الفرعي استدعاء نفسه. في هذه الحالة ، لا يهتم الكمبيوتر. هو ، كما هو الحال دائمًا ، ينفذ باستمرار الأوامر التي التقى بها من أعلى إلى أسفل.
إذا كنت تتذكر الرياضيات ، فهناك يمكنك تلبية مبدأ الاستقراء الرياضي. على النحو التالي: & nbsp؛ بعض العبارات صحيحة لكل طبيعي & nbsp؛ n إذا
نبسب ؛ نبسب ؛ 1) صالح لـ & nbsp؛ n = 1 ؛
نبسب ؛ نبسب ؛ 2) من صحة العبارة لأي تعسفي طبيعي n = k & nbsp ؛ ويترتب على ذلك أنها صحيحة لـ & nbsp؛ n = k + 1 .
في البرمجة ، هذه التقنية تسمى العودية.
التكرار strong> طريقة لتعريف مجموعة من الكائنات وفقًا للمجموعة نفسها ، بناءً على حالات أساسية بسيطة معينة.
التكرار strong> هو إجراء (وظيفة) تستدعي نفسها مباشرة أو من خلال إجراءات ووظائف أخرى.
مثال على إجراء تكراري: span>
تسجيل باطل (int a)
{
نبسب ؛ إذا (a & gt؛ 0) {Rec (a-1) ؛ }
نبسب ؛ Console.WriteLine (أ) ؛
}
تخطيطيًا ، يمكن تمثيل عمل العودية كمخطط انسيابي. span> span >
Rec () & nbsp؛ يتم تنفيذ الإجراء باستخدام المعلمة 3 بعد ذلك ، داخل الإجراء مع المعلمة 3 ، يتم استدعاء الإجراء مع المعلمة 2 ، وهكذا ، حتى يتم استدعاء الإجراء مع المعلمة 0. work. ثم يتم نقل التحكم مرة أخرى إلى الإجراء بالمعامل 1 ، كما أنه ينهي عمله بطباعة الرقم 1 ، وهكذا. قبل الإجراء مع المعلمة 3. نبسب ؛
يتم تخزين جميع الإجراءات التي تسمى في الذاكرة حتى يكملوا عملهم. يُطلق على عدد الإجراءات المتزامنة اسم عمق العودية strong>.
|
اكتشفنا أن العودية هي التنفيذ المتكرر للأوامر المضمنة في روتين فرعي. وهذا بدوره يشبه عمل الدورة. هناك لغات برمجة يكون فيها بناء الحلقة غائبًا على الإطلاق ، على سبيل المثال ، Prolog. & nbsp؛
دعونا نحاول محاكاة عمل الحلقة for . & nbsp؛
تحتوي حلقة for على متغير عداد الخطوة. في روتين فرعي متكرر ، يمكن تمرير مثل هذا المتغير كمعامل. span>
<قبل>
// الإجراء LoopImitation () مع معلمتين
// المعلمة الأولى & ndash؛ عداد الخطوة ، المعلمة الثانية & ndash ؛ العدد الإجمالي للخطوات
LoopImitation الفراغ الثابت (int i، int n)
{
Console.WriteLine (& quot؛ Hello N & quot؛ + i)؛ // عبارة تتكرر لأي قيمة i
إذا (i & lt؛ n) // حتى يساوي عداد الحلقة n ،
{
LoopImitation (i + 1، n) ؛ // استدعاء جديد إجراء المثال ، مع المعلمة i + 1 (انتقل إلى قيمة i التالية) code>
}
}
|
العودية والتكرار h5>
لفهم العودية ، تحتاج إلى فهم العودية ... q>
نبسب ؛
التكرار code> & nbsp؛ في البرمجة - خطوة واحدة tt> لعملية معالجة البيانات الدورية. & nbsp؛
غالبًا ما تستخدم الخوارزميات التكرارية في الخطوة الحالية (التكرار) نتيجة نفس العملية أو الإجراء المحسوب في الخطوات السابقة. & nbsp ؛ أحد الأمثلة على هذه الحسابات هو حساب علاقات التكرار. & nbsp ؛
مثال بسيط على القيمة العودية هو العامل: \ (N! = 1 \ cdot 2 \ cdot 3 \ cdot \ ... \ \ cdot N \) span>.
حساب القيمة في كل خطوة (التكرار) هو \ (N = N \ cdot i \) . & nbsp؛ عند حساب قيمة \ (N \) ، نأخذ القيمة المخزنة بالفعل & nbsp؛ \ (N \) span >. <ر />
يمكن أيضًا وصف مضروب الرقم باستخدام الصيغة المتكررة code>:
\ (\ start {equation *} n! = \ begin {cases} 1 & amp؛ \ text {n & lt؛ = 1،} \\ (n-1)! \ cdot n & amp؛ \ text {n & gt؛ 1.} \ end {cases} \ end {equation *} \)
قد تلاحظ أن هذا الوصف ليس أكثر من وظيفة تكرارية.
هنا السطر الأول ( \ (n & lt؛ = 1 \) ) هو الحالة الأساسية (شرط إنهاء العودية) والسطر الثاني هو الانتقال إلى الخطوة التالية. نبسب ؛
نبسب ؛
<الجسم>
دالة التوزيع العودية strong> |
الخوارزمية التكرارية strong> |
<قبل>
static int Factorial (int n) {
إذا (n & gt؛ 1)
عودة ن * عاملي (ن - 1) ؛
آخر يعود 1 ؛
}
|
<قبل>
int x = 1؛
لـ (int i = 2 ؛ i & lt ؛ = n ؛ i ++)
س = س * ط ؛
Console.WriteLine ("٪ d"، x)؛
|
يجب أن يكون مفهوماً أن استدعاءات الوظائف تنطوي على بعض النفقات الإضافية ، لذا فإن حساب العوامل غير العودية سيكون أسرع قليلاً. & nbsp؛
الخلاصة: strong> حيث يمكنك كتابة برنامج باستخدام خوارزمية تكرارية بسيطة ، بدون تكرار ، فأنت بحاجة إلى الكتابة بدون تكرار. ولكن لا يزال هناك فئة كبيرة من المشاكل حيث يتم تنفيذ العملية الحسابية فقط عن طريق العودية.
من ناحية أخرى ، غالبًا ما تكون الخوارزميات العودية أكثر قابلية للفهم.
|
الترجمة التكرارية لرقم من نظام رقمي إلى آخر h5>
في & nbsp ؛ في بعض المواقف من الإجراءات ، يمكنك استخدام كلمة return & nbsp؛ بدون وسيطة - أي في الواقع ، لا يزال الإجراء لا يُرجع أي شيء. & nbsp ؛ قد يكون هذا مفيدًا عند التكرار ، عندما & nbsp ؛ return & nbsp؛ code> يُستخدم لإنهاء الهبوط عند الحالات الأساسية لقيم المعلمات التي يتم تكرارها. على سبيل المثال ، قد يبدو الإجراء الذي يحول رقمًا من عشري إلى ثنائي كما يلي:
ثابت & نبسب ؛ باطل printTwo (int n)
{& nbsp؛ & nbsp؛
نبسب ؛ إذا (ن == 0) عودة ؛
نبسب ؛ نبسب ؛ printTwo (ن / 2) ؛
نبسب ؛ إذا (ن٪ 2 == 0) Console.Write (0) ؛
نبسب ؛ آخر نبسب ؛ وحدة التحكم. الكتابة (1) ؛
}
|
مهمة h6>
في أبجدية لغة القبيلة "Tumba-Yumba" ؛ أربعة أحرف: "K" ، "L" ، "M" و & quot؛ N & quot ؛. تحتاج إلى عرض جميع الكلمات التي تتكون من أحرف n التي يمكن إنشاؤها من أحرف هذه الأبجدية. tt>
المشكلة هي مشكلة القوة الغاشمة العادية التي يمكن اختزالها إلى مشكلة أصغر.
سنقوم باستبدال الأحرف بالتسلسل.
يمكن أن يكون الموضع الأول للكلمة واحدًا من الأحرف الأربعة للأبجدية (K. L ، M ، N).
لنضع الحرف K أولاً. بعد ذلك ، من أجل الحصول على جميع المتغيرات التي تحتوي على الحرف الأول K ، تحتاج إلى تعداد جميع مجموعات الأحرف الممكنة & nbsp؛ في المواضع المتبقية n - 1 & nbsp؛ وما إلى ذلك. (انظر الصورة). div>
وهكذا ، يتم تقليل المشكلة إلى حل أربع مسائل طولها n - 1 .
نبسب ؛
تكرار أكثر من n حرفًا بشكل متكرر h6>
w [0] = & # 39؛ K & # 39 ؛؛ // كرر خلال آخر أحرف L-1
ث [0] = & # 39 ؛ L & # 39 ؛؛ // كرر خلال آخر أحرف L-1
ث [0] = & # 39 ؛ M & # 39 ؛؛ // كرر خلال آخر أحرف L-1
ث [0] = & # 39 ؛ N & # 39 ؛؛ // كرر خلال آخر أحرف L-1
w - سلسلة أحرف تخزن كلمة العمل.
وهكذا ، حصلنا على العودية. & nbsp ؛ يمكننا ترتيب حل المشكلة في شكل إجراء تكراري. & nbsp ؛
يبقى لتحديد متى سينتهي العودية؟ عندما يتم تعيين جميع الأحرف ، أي أن عدد الأحرف المحددة هو n . في هذه الحالة ، تحتاج إلى عرض الكلمة الناتجة على الشاشة والخروج من الإجراء.
سيبدو برنامج C # هكذا. div>
// w - معلمة قابلة للتغيير strong> (سلسلة-نتيجة)
// يتم تمرير إجراء TumbaWords الأبجدية كسلسلة أحرف ،
// الكلمة word وعدد الأحرف المحددة بالفعل (في البداية & ndash ؛ 0)
TumbaWords باطل ثابت (سلسلة A ، سلسلة المرجع w ، int N)
{
إذا (N == w.Length) // w.Length - عدد الأحرف في السلسلة
{
نبسب ؛ // إذا تم بالفعل تعيين جميع الأحرف للكلمة ، & nbsp؛ نبسب ؛
نبسب ؛ // ثم من الضروري إخراج سلسلة وإنهاء الإجراء
Console.WriteLine (ث) ؛
يعود؛
}
لـ (int i = 0؛ i & lt؛ w.Length؛ i ++) // إذا كان الشرط أعلاه خاطئًا (أي أنه لا توجد مسافات بين جميع الأحرف ،
{
نبسب ؛ نبسب ؛ // إذا كان الشرط أعلاه خاطئًا (أي ، ليست كل الأحرف متباعدة ، & nbsp؛
نبسب ؛ // ثم في الحلقة نمر بجميع أحرف الأبجدية و
نبسب ؛ // ضع الحرف بالتناوب على أول مساحة خالية
w + = A [i] ؛
TumbaWords (A ، المرجع w ، N + 1) ؛
ث = ث إزالة (طول ث - 1) ؛ // ثم قم بإزالة آخر حرف مضاف ،
نبسب ؛ // لعمل كلمة جديدة بنفس البادئة
}
}
فراغ ثابت رئيسي ()
{
int n = Convert.ToInt32 (Console.ReadLine ()) ،
كلمة سلسلة = & quot؛ & quot ؛؛
TumbaWords (& quot؛ KLMN & quot ؛، المرجع word ، 0) ؛
}
لاحظ strong> أن w معلمة قابلة للتغيير (سلسلة نتيجة)! u>
|