الحالة الأفضل والأسوأ والمتوسطة
الخوارزمية نفسها قد تنهي في خطوة أو في مليون خطوة؛ يعتمد ذلك على المدخل. ⏱ نحو 25 دقيقة.
- تميّز الحالة الأفضل والأسوأ والمتوسطة لخوارزمية.
- تحسب عدد عمليات الخوارزمية بعدّاد في الكود.
- تشرح لماذا نعتمد على الحالة الأسوأ غالبًا.
- تحلل البحث الخطي والترتيب بالإدراج في الحالات الثلاث.
١الخوارزمية نفسها، وأعمال مختلفة
البحث الخطي: نفحص العناصر من الأول حتى نجد المطلوب. كم مقارنة يحتاج؟ يعتمد على مكان العنصر. جرّب المحاكاة مرتين: مرة لعنصر في البداية، ومرة لعنصر غير موجود:
٢ثلاث حالات نحللها
| الحالة | متى تحدث في البحث الخطي؟ | عدد المقارنات (n عنصرًا) |
|---|---|---|
| الأفضل Best Case | العنصر في الموقع الأول. | 1 |
| الأسوأ Worst Case | العنصر في الآخر، أو غير موجود. | n |
| المتوسطة Average Case | العنصر في موقع عشوائي. | نحو n ÷ 2 |
نتحقق من ذلك بالحساب. نبحث عن كل عنصر في قائمة من 10 عناصر، ونعدّ المقارنات:
def linear_search(a, x): comparisons = 0 for v in a: comparisons += 1 if v == x: break return comparisons a = list(range(1, 11)) # 10 عناصرcounts = [linear_search(a, x) for x in a]print("كل الحالات:", counts)print("الأفضل:", min(counts))print("الأسوأ:", max(counts))print("المتوسط:", sum(counts) / len(counts))
٣لماذا نهتم بالحالة الأسوأ أكثر؟
لأنها ضمان: مهما كان المدخل، لن تتجاوز الخوارزمية هذا العدد. نظام حجز الطيران لا يكفيه أن يكون سريعًا «في المتوسط»؛ يجب ألا يتعطل أبدًا في أسوأ يوم.
| الحالة | فائدتها |
|---|---|
| الأفضل | قليلة الفائدة؛ تحدث نادرًا ولا تضمن شيئًا. |
| المتوسطة | تصف الأداء المعتاد، لكن حسابها يحتاج معرفة توزيع المدخلات. |
| الأسوأ | الأهم عادة: حد أعلى مضمون للأداء. |
٤الحالات في خوارزمية ترتيب
الترتيب بالإدراج يُدخل كل عنصر في مكانه الصحيح في الجزء المرتب. شاهد كيف يختلف عمله على قائمة شبه مرتبة وعلى قائمة معكوسة:
def insertion_comparisons(a): a = list(a) count = 0 for i in range(1, len(a)): j = i while j > 0: count += 1 if a[j - 1] > a[j]: a[j - 1], a[j] = a[j], a[j - 1] j -= 1 else: break return count n = 100print("مرتبة:", insertion_comparisons(range(n)))print("معكوسة:", insertion_comparisons(range(n, 0, -1)))
على قائمة مرتبة أصلًا: 99 مقارنة فقط (الحالة الأفضل). وعلى قائمة معكوسة: 4950 مقارنة (الحالة الأسوأ). الخوارزمية نفسها، والفرق 50 ضعفًا بسبب المدخل وحده.
توقّع وتحقّق
أسوأ حالة للبحث الخطي في 50 عنصرًا:
أفضل حالة للبحث الخطي:
الحالة التي تعطي ضمانًا للأداء:
الترتيب بالإدراج أسرع ما يكون على قائمة:
الخلاصة
- أداء الخوارزمية قد يتغير بتغير ترتيب المدخلات لا حجمها فقط.
- البحث الخطي: الأفضل 1، والأسوأ
n، والمتوسط نحوn ÷ 2. - الحالة الأسوأ ضمان للأداء، لذلك هي الأهم عادة.
- الإدراج: سريع جدًّا على المرتبة، وبطيء على المعكوسة.
تحدٍّ برمجي: حلّل البحث الخطي
متوسطقائمة فيها 8 أسماء. احسب عدد مقارنات البحث الخطي عن كل اسم، وعن اسم غير موجود، ثم اطبع الأفضل والأسوأ والمتوسط (للأسماء الموجودة).
- دالة تُرجع عدد المقارنات (تتوقف عند الإيجاد).
- اطبع: غير موجود: 8
- اطبع: الأفضل: 1 ثم الأسوأ: 8 ثم المتوسط: 4.5
ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:
names = ["أحمد", "سارة", "خالد", "منى", "فهد", "ريم", "علي", "هند"]💡 تلميح 1
counts = [comparisons(names, x) for x in names]💡 تلميح 2
sum(counts) / len(counts)حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
names = ["أحمد", "سارة", "خالد", "منى", "فهد", "ريم", "علي", "هند"] def comparisons(a, x): c = 0 for v in a: c += 1 if v == x: break return c print("غير موجود:", comparisons(names, "سلمان"))counts = [comparisons(names, x) for x in names]print("الأفضل:", min(counts))print("الأسوأ:", max(counts))print("المتوسط:", sum(counts) / len(counts))