Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

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

آخر تحديث

يعثر البحث الثنائي على قيمة مستهدفة في مصفوفة **مرتبة** عبر تقسيم نافذة البحث إلى النصف مرارًا. يقارن العنصر الأوسط بالقيمة المستهدفة: التطابق ينهي البحث؛ وإلا يُستبعد النصف الذي لا يمكن أن يحتوي على الهدف وتتقلص النافذة إلى النصف الآخر. كل مقارنة تستبعد نصف العناصر المتبقية، ولهذا يعمل في O(log n) — فالبحث في مليون قيمة مرتبة يحتاج على الأكثر إلى نحو 20 مقارنة.

تعرض الرسوم المتحركة أعلاه المؤشرات lo وmid وhi وتُخفت النصف المستبعد بعد كل مقارنة. الشرط المسبق الوحيد غير القابل للتفاوض: يجب أن تكون المصفوفة مرتبة مسبقًا — مع البيانات غير المرتبة تحتاج إلى البحث الخطي أو إلى ترتيب أولًا (انظر الترتيب بالدمج). وفكرة التقسيم إلى النصف نفسها هي أساس شجرة البحث الثنائية.

التعقيد الزمني والمكاني

الحالةالتعقيدملاحظات
أفضل حالةO(1)العنصر الأوسط هو الهدف في المقارنة الأولى.
الحالة المتوسطةO(log n)كل مقارنة تقسم النافذة المتبقية إلى النصف.
أسوأ حالةO(log n)تتقلص النافذة إلى عنصر واحد قبل العثور على الهدف أو التأكد من غيابه.
المساحةO(1)النسخة التكرارية تحتفظ فقط بالمؤشرات lo وhi وmid.

خطوة بخطوة

الخطوةما الذي يحدث
1اضبط lo على أول مؤشر وhi على آخر مؤشر في المصفوفة المرتبة.
2احسب المؤشر الأوسط: mid = (lo + hi) // 2.
3إذا كان a[mid] يساوي الهدف، أعد mid — تم العثور عليه.
4إذا كان a[mid] **أصغر** من الهدف، فلا يمكن أن يكون الهدف إلا في النصف الأيمن: اضبط lo = mid + 1.
5إذا كان a[mid] **أكبر** من الهدف، فابحث في النصف الأيسر: اضبط hi = mid - 1.
6كرر من الخطوة 2 ما دام lo <= hi؛ إذا فرغت النافذة فالهدف غير موجود في المصفوفة.

مثال محلول

البحث عن 5 في [1, 2, 3, 5, 7, 8, 9]:

الجولةالنافذة (lo..hi)mida[mid]الإجراء
1[1, 2, 3, 5, 7, 8, 9] (0..6)35a[3] = 5 — تم العثور على الهدف عند المؤشر 3.

بحث فاشل، خطوة بخطوة

البحث عن 4 في المصفوفة نفسها يوضح كيف تفرغ النافذة:

الجولةالنافذة (lo..hi)mida[mid]الإجراء
10..6355 > 4 — ابحث في النصف الأيسر، hi = 2.
20..2122 < 4 — ابحث في النصف الأيمن، lo = 2.
32..2233 < 4 — يصبح lo مساويًا 3 وتفرغ النافذة: غير موجود.

متى تستخدم البحث الثنائي

استخدمه عندماتجنبه عندما
تكون البيانات مرتبة مسبقًا (أو تبحث فيها مرات عديدة)تكون البيانات غير مرتبة وتُبحث مرة واحدة فقط — الترتيب أولًا يكلف O(n log n)
تدعم المجموعة الوصول العشوائي السريع (المصفوفات)لا تملك سوى وصول تسلسلي (القوائم المتصلة)
تكون مجموعة البيانات كبيرة — O(log n) يتألق على نطاق واسعتكون مجموعة البيانات صغيرة جدًا — المسح البسيط بنفس السرعة وأبسط

تنفيذ نظيف وقابل للتشغيل لخوارزمية Binary Search بلغات Python, JavaScript, Java, C++, C, Pseudocode. اختر لغة، وانسخ الكود، أو افتحه محمّلًا مسبقًا في ساحة تجربة Coddy.

كود Binary Search بلغة Python

Python
1def binary_search(a, target):2    lo, hi = 0, len(a) - 13    while lo <= hi:4        mid = (lo + hi) // 25        if a[mid] == target:6            return mid7        if a[mid] < target:8            lo = mid + 1  # search the right half9        else:10            hi = mid - 1  # search the left half11    return -112
13
14nums = [1, 2, 3, 5, 7, 8, 9]  # must be sorted15print("Index of 5:", binary_search(nums, 5))16print("Index of 4:", binary_search(nums, 4))
شغّل هذا الكود في ساحة تجربة Python

الأسئلة الشائعة عن البحث الثنائي

ما التعقيد الزمني للبحث الثنائي؟
O(log n) في الحالتين المتوسطة والأسوأ، لأن كل مقارنة تقسم نافذة البحث المتبقية إلى النصف، وO(1) في أفضل حالة عندما يكون أول عنصر أوسط هو الهدف. تستخدم النسخة التكرارية مساحة إضافية O(1).
لماذا يتطلب البحث الثنائي مصفوفة مرتبة؟
خطوة التقسيم إلى النصف تعتمد على الترتيب: مقارنة الهدف بالعنصر الأوسط لا تخبرك أي نصف تستبعد إلا إذا كان كل ما على يسار الوسط أصغر وكل ما على يمينه أكبر. مع البيانات غير المرتبة يصبح هذا الاستنتاج باطلًا — استخدم البحث الخطي بدلًا منه، أو رتّب أولًا.
ما الفرق بين البحث الثنائي والبحث الخطي؟
يمسح البحث الخطي العناصر واحدًا تلو الآخر (O(n)) ويعمل مع أي مصفوفة؛ بينما يقسم البحث الثنائي نافذة البحث في مصفوفة مرتبة إلى النصف (O(log n)) لكنه يتطلب مدخلات مرتبة. مع حفنة من العناصر يكون الفرق ضئيلًا — أما على نطاق واسع فيفوز البحث الثنائي بفارق حاسم.
كم عدد المقارنات التي يحتاجها البحث الثنائي؟
على الأكثر نحو log2(n) + 1: تغطي 10 مقارنات 1,000 عنصر، و20 مقارنة تغطي 1,000,000. هذا النمو اللوغاريتمي هو ما يجعله وسيلة البحث الافتراضية في البيانات المرتبة.
ما خطأ الفيض (overflow) الكلاسيكي في البحث الثنائي؟
حساب الوسط بالشكل (lo + hi) / 2 قد يسبب فيضًا في الأعداد الصحيحة ذات الحجم الثابت عندما يتجاوز lo + hi الحد الأقصى للنوع. الصيغة الآمنة هي mid = lo + (hi - lo) / 2. في Python لا يهم هذا (أعداد صحيحة بدقة غير محدودة)، لكنه في Java/C/C++ خطأ حقيقي وشهير.
هل البحث الثنائي هو نفسه شجرة البحث الثنائية؟
يتشاركان فكرة التقسيم إلى النصف لكنهما يختلفان في البنية: البحث الثنائي خوارزمية تعمل على مصفوفة مرتبة، بينما شجرة البحث الثنائية بنية بيانات متصلة تحافظ على مفاتيحها مرتبة بحيث ينزل البحث يسارًا أو يمينًا عند كل عقدة.
Coddy programming languages illustration

أتقن الخوارزميات مع Coddy

ابدأ الآن