البحث والفرز (Searching & Sorting)

خوارزميات البحث والفرز هي العمود الفقري لكل الأنظمة:

  • قواعد البيانات
  • أنظمة التشغيل
  • محركات الألعاب
  • الذكاء الاصطناعي
  • معالجة البيانات
  • مواقع التواصل
  • البرمجيات العلمية
  • الـ Big Data
  • المحركات الرسومية
  • أنظمة الترتيب والفلترة

لو ما بتعرف كيف تعمل search و sort، فإنك ما بتعرف كيف تشتغل أغلب البرامج اللي حولك.
اليوم رح نفصّل أشهر خوارزميات البحث والفرز، مع شرح المفهوم الداخلي، والتحليل، والتطبيق العملي.

الجزء الأول: البحث (Searching)

1. البحث الخطي Linear Search

أبسط طريقة بحث…
تبحث عنصر عنصر لغاية ما تلاقي العنصر المطلوب.

الفكرة:

  • ابدأ من البداية
  • افحص كل عنصر
  • إذا وجدت القيمة → انتهى
  • إذا وصلت للنهاية ولم تجدها → غير موجودة

الزمن:

  • الأسوأ O(n)
  • الأفضل (إذا العنصر بالأول) O(1)
  • المتوسط O(n)

الكود:

int linearSearch(int arr[], int n, int target) {
    for (int i = 0; i < n; i++) {
        if (arr[i] == target)
            return i;
    }
    return -1;
}

مميزات:

✔ سهل جدًا
✔ لا يحتاج ترتيب مسبق
✔ يعمل مع أي نوع بيانات

عيوب:

❌ بطيء مع البيانات الكبيرة
❌ غير مناسب للبحث المستمر


2. البحث الثنائي Binary Search

واحدة من أهم وأسرع خوارزميات البحث.

الشرط الرئيسي:

المصفوفة يجب أن تكون مرتبة
بدون ترتيب، Binary Search مستحيل يشتغل.

الفكرة:

  • اختر منتصف المصفوفة
  • إذا الهدف أكبر → نبحث باليمين
  • إذا الهدف أصغر → نبحث باليسار
  • تكرار العملية حتى نجد العنصر أو تصبح الحدود غير صالحة

الزمن:

  • الأسوأ O(log n)
  • الأفضل O(1)
  • المتوسط O(log n)

الكود:

int binarySearch(int arr[], int n, int target) {
    int left = 0, right = n - 1;

    while (left <= right) {
        int mid = (left + right) / 2;

        if (arr[mid] == target)
            return mid;
        else if (arr[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }

    return -1;
}

مميزات:

✔ سريع جدًا
✔ يعمل بكفاءة عالية على البيانات الكبيرة
✔ مناسب للأنظمة الحقيقية

عيوب:

❌ يحتاج ترتيب
❌ لا يعمل على Linked List
❌ معقد أكثر من Linear Search


الجزء الثاني: الفرز (Sorting)

الفرز أساس كل شيء…
لا يوجد بحث فعال بدون فرز، ولا يوجد قاعدة بيانات تعمل بكفاءة بدون فرز، ولا يوجد نظام ترشيح ذكي بدون ترتيب.

هنشرح 3 خوارزميات:

  1. Bubble Sort
  2. Selection Sort
  3. Quick Sort (الأسرع بينهم)

1. Bubble Sort – الفرز الفقاعي

أبسط خوارزمية فرز… لكنها الأبطأ.

الفكرة:

  • مرر على المصفوفة
  • قارن كل زوج متتالٍ
  • إذا الأول أكبر → بدّلهم
  • كرر العملية n مرات

الزمن:

  • الأسوأ: O(n²)
  • الأفضل (لو مرتّبة): O(n)
  • المتوسط: O(n²)

الكود:

void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                swap(arr[j], arr[j + 1]);
            }
        }
    }
}

لماذا هو بطيء؟

لأنه يقارن عدد ضخم من الأزواج بدون ذكاء.

مميزات:

✔ بسيط
✔ سهل الفهم

عيوب:

❌ أبطأ طريقة ممكن تفكر فيها
❌ غير عملي للمشاريع الحقيقية


2. Selection Sort

التفكير الذكي بدل Bubble Sort الغبي.

الفكرة:

  • مرر على المصفوفة
  • في كل دورة → ابحث عن أصغر قيمة
  • ضعها في مكانها الصحيح
  • كرر العملية

الزمن:

  • الأسوأ: O(n²)
  • المتوسط: O(n²)
  • الأفضل: O(n²) (مفيش فرق)

الكود:

void selectionSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int minIndex = i;

        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex])
                minIndex = j;
        }

        swap(arr[i], arr[minIndex]);
    }
}

مميزات:

✔ سهل
✔ أفضل من Bubble Sort
✔ عمليات التبديل قليلة (swap)

عيوب:

❌ زمنه O(n²)
❌ ليس الأفضل على بيانات كبيرة


3. Quick Sort – الفرز السريع

واحدة من أسرع خوارزميات الفرز في العالم
تُستخدم في:

  • Linux Kernel
  • المكتبات القياسية
  • الأنظمة المالية
  • قواعد البيانات
  • محركات الألعاب

الفكرة:

مبنية على divide and conquer:

  1. اختر pivot
  2. ضع كل القيم الأصغر على يسار الـ pivot
  3. ضع الأكبر على يمين الـ pivot
  4. كرر العملية على اليمين واليسار

الزمن:

  • الأفضل: O(n log n)
  • المتوسط: O(n log n)
  • الأسوأ (نادرًا): O(n²)

الكود الأساسي:

int partition(int arr[], int low, int high) {
    int pivot = arr[high];
    int i = low - 1;

    for (int j = low; j < high; j++) {
        if (arr[j] < pivot) {
            i++;
            swap(arr[i], arr[j]);
        }
    }

    swap(arr[i + 1], arr[high]);
    return i + 1;
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);

        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

مميزات:

✔ الأسرع عمليًا
✔ مناسب للبيانات الكبيرة
✔ يستخدم في الأنظمة الحديثة

عيوب:

❌ الأسوأ O(n²)
❌ قد يحتاج stack كبير في recursion


مقارنة شاملة بين خوارزميات الفرز

الخوارزميةالزمنالأفضلية
Bubble SortO(n²)أسوأ واحدة
Selection SortO(n²)متوسط
Quick SortO(n log n)الأفضل عمليًا

مقارنة بين Linear و Binary Search

البحثالشرطالزمنالأفضلية
Linear Searchلا يحتاج ترتيبO(n)بسيط فقط
Binary Searchيحتاج ترتيبO(log n)سريع جدًا

تطبيقات عملية قوية

تطبيق 1: بحث عن عنصر داخل مصفوفة كبيرة

  • استخدم linear لو المصفوفة غير مرتبة
  • استخدم binary لو المصفوفة مرتّبة

تطبيق 2: ترتيب العلامات

  • Quick Sort أفضل اختيار

تطبيق 3: البحث داخل قاعدة بيانات صغيرة في الذاكرة

  • Binary Search + QuickSort combo

تطبيق 4: معالجة بيانات مستمرة real-time

  • Quick Sort جدًا مناسب

الأخطاء الشائعة

❌ تنفيذ Binary Search على بيانات غير مرتبة
❌ خلط pivot بشكل سيء في Quick Sort
❌ استخدام Bubble Sort على بيانات كبيرة (انتحار برمجي)
❌ نسيان حدود high و low في Quick Sort
❌ العمل على مصفوفة منتهية الحدود في الفرز
❌ عدم التعامل مع المؤشرات في recursion بشكل صحيح


الخلاصة النهائية

اليوم تعلمت:

✔ Linear Search – البحث الخطي

✔ Binary Search – البحث الثنائي

✔ Bubble Sort – الفرز الفقاعي

✔ Selection Sort – فرز الاختيار

✔ Quick Sort – الفرز السريع (الأفضل)

✔ التحليل الزمني للخوارزميات

✔ المقارنة بين طرق البحث والفرز

✔ تطبيقات عملية

✔ أخطاء يجب تجنبها

وهذا الدرس هو أساس لكل شيء قادم في هياكل البيانات:

  • Trees
  • Heaps
  • Priority Queue
  • Hashing
  • Graph Algorithms
  • Dynamic Programming

اكتشاف المزيد من كود التطور

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك رد

Scroll to Top