استخدام العَودية لحل المسائل

12.5 استخدام العَودية لحل المسائل

أهداف التعلم

في نهاية هذا القسم، ينبغي أن تكون قادرًا على:

  • استخدام العَودية للبحث بكفاءة في قائمة.
  • عرض حل لمشكلة الأبراج الثلاثة.

البحث الثنائي

عادةً ما يتطلب البحث في قائمة مرتبة فحص كل عنصر. إذا لم يُعثر على العنصر المطلوب، فقد يستغرق البحث وقتًا طويلاً.

البحث الثنائي خوارزمية عَودية تُستخدم للبحث بكفاءة في القوائم المرتبة. في كل خطوة عَودية، يُستبعد حوالي نصف العناصر بوصفها غير مطابقة محتملة، لذا يتقدم البحث بشكل أسرع بكثير.

يبدأ البحث الثنائي بفحص العنصر الأوسط في القائمة. إذا عُثر على مفتاح البحث، تُرجع الخوارزمية الموقع المطابق (الحالة الأساسية). وإلا، يتكرر البحث على حوالي نصف القائمة. إذا كان المفتاح أكبر من العنصر الأوسط، فلا بد أن المفتاح في النصف الأيمن، والعكس صحيح. تستمر العملية بفحص العنصر الأوسط للنصف المتبقي من القائمة.

مثال 12.3

البحث الثنائي

    """ Binary Search """

    def binary_search(search_list, low, high, key):

      # التحقق من الحالة الأساسية
      if high > low:
        mid = (high + low) // 2
    
        # إذا كان العنصر موجودًا في المنتصف
        if search_list[mid] == key:
          return mid

        # الحالة العَودية: تحديد أي مصفوفة فرعية يجب فحصها
        # المصفوفة الفرعية اليمنى
        elif key > search_list[mid]:
          return binary_search(search_list, mid + 1, high, key)

        # المصفوفة الفرعية اليسرى
        else:
          return binary_search(search_list, low, mid - 1, key)

      else:
        # المفتاح غير موجود (حالة أساسية أخرى)
        return "Not found"

    # قائمة اختبار
    in_list = [1, 3, 13, 16, 19, 22, 27, 32, 48, 66, 78, 99, 111, 122]

    # استدعاء دالّة البحث الثنائي
    print(binary_search(in_list, 0, len(in_list)-1, 48)) # المفتاح موجود في الفهرس 8

    print(binary_search(in_list, 0, len(in_list)-1, 86)) # المفتاح غير موجود

ناتج الشِفرة أعلاه:

    8
    Not found

نقطة تحقق

البحث الثنائي

مفاهيم تطبيقية

البحث الثنائي

1.
أي قائمة يمكن البحث فيها باستخدام خوارزمية البحث الثنائي؟
  1. [5, 2, 7, 1, 8]
  2. [9, 8, 7, 6, 5]
  3. [4, 5, 6, 7, 8]
2.
إذا تم استدعاء الدالّة binary_search() مع low = 4، و high = 7، فإن mid تُحسب لتكون _____
  1. 5
  2. 6
  3. 11
3.
كم عدد استدعاءات الدالّة binary_search() التي تحدث في العرض التوضيحي؟
  1. 3
  2. 4
  3. 8
4.
كم عدد استدعاءات الدالّة binary_search() التي تحدث في مثال الشِفرة عند البحث عن 86؟
  1. 4
  2. 14

حل مشكلة الأبراج الثلاثة

كما نوقش في قسم سابق، يمكن حل مشكلة الأبراج الثلاثة بالعَودية. يعتمد الحل على استدعاء حل المسألة الأصغر التالية مرتين. وكما هو موضح في مثال الشِفرة أدناه، يمكن للحل العَودي أن يحل المشكلة لأي عدد من الحلقات.

مثال 12.4

حل مشكلة N من الأبراج

حل مشكلة الأبراج الثلاثة بسيط بالعَودية. في الشِفرة أدناه، تُرقَّم الحلقات من الأعلى إلى الأسفل. أصغر حلقة هي 1، والحلقة التالية هي 2، وعند حل المشكلة لثلاث حلقات، تكون الحلقة السفلية هي 3.

    """ Solving the towers problem recursively """

    def three_towers(N, source_tower, dest_tower, temp_tower):
        # الحالة الأساسية: نقل الحلقة السفلية من البرج المصدر إلى البرج الهدف
        if N==1:
            print("Move ring 1 from tower", source_tower, "to tower", dest_tower)
            return # الخروج عند الوصول إلى الحالة الأساسية

        # الحالة العَودية
        # استدعاء النسخة الأصغر من المشكلة:
        # لنقل مكدس N-1 إلى البرج الأوسط
        three_towers(N-1, source_tower, temp_tower, dest_tower)

        # نقل الحلقة N إلى البرج الهدف
        print("Move ring", N, "from tower", source_tower, "to tower", dest_tower)

        # استدعاء النسخة الأصغر من المشكلة:
        # لنقل مكدس N-1 الآن من البرج الأوسط
        # إلى البرج الهدف
        three_towers(N-1, temp_tower, dest_tower, source_tower)

    # شِفرة اختبار
    print("Solution for 3 rings:")
    three_towers(3, 't1', 't3', 't2') # t1، t2، t3 هي الأبراج

ناتج الشِفرة أعلاه:

    Solution for 3 rings:
    Move ring 1 from tower t1 to tower t3
    Move ring 2 from tower t1 to tower t2
    Move ring 1 from tower t3 to tower t2
    Move ring 3 from tower t1 to tower t3
    Move ring 1 from tower t2 to tower t1
    Move ring 2 from tower t2 to tower t3
    Move ring 1 from tower t1 to tower t3

مفاهيم تطبيقية

حل مشكلة الأبراج الثلاثة

5.
لأربع حلقات، كم عدد الأسطر الإجمالية التي ستطبعها الدالّة three_towers()؟
  1. 7
  2. 15
6.
هل سيكون الحل التكراري لمشكلة الأبراج الثلاثة أكثر تعقيدًا أم أقل تعقيدًا؟
  1. أكثر تعقيدًا
  2. أقل تعقيدًا

جرّب بنفسك

توليفات العملات

اكتب دالّة عَودية باسم print_H_T() تُنتج جميع التوليفات الممكنة للوجه ("H") والذيل ("T") لعدد معين من رميات العملة.

مثال: لثلاث عملات، يجب أن يطبع البرنامج المخرجات الموضحة أدناه.

    HHH
    HHT
    HTH
    HTT
    THH
    THT
    TTH
    TTT