QuickSort: دليل شامل لخوارزمية الفرز السريع في بايثون وجافا (مع تحليل الأداء)

استمع للبودكاست حوار شيق بين لمى وأبو عمر
0:00 / 0:00

مقدمة: عندما أضعت مفاتيح السيارة… والـ QuickSort!

بتذكر مرة، كنت مستعجل كتير عشان ألحق موعد مهم. نزلت من البيت، وفتحت الباب، بس وين المفاتيح؟ 🤦‍♂️ دورت بكل جيوبي، بالكنبايات، تحت السجاد… حرفياً قلبت البيت فوقاني تحتاني! بالنهاية، اكتشفت إنهم كانوا جوا الثلاجة! (لا تسألوني كيف وصلوا هناك 😂). هاي التجربة علمتني شغلة مهمة: الترتيب والتنظيم بيوفروا وقت وجهد كبيرين. ونفس الشي بينطبق على البيانات في عالم البرمجة. وهون بيجي دور خوارزميات الفرز، وبالأخص خوارزمية الـ QuickSort اللي رح نحكي عنها اليوم.

الـ QuickSort هي خوارزمية فرز قوية وفعالة، تعتمد على مبدأ “فرق تسد” (Divide and Conquer). بتعتبر من أسرع خوارزميات الفرز الموجودة، وبتستخدم على نطاق واسع في تطبيقات مختلفة. في هالمقالة، رح نتعمق في طريقة عملها، ونحلل أدائها، ونطبقها عملياً في لغتي بايثون وجافا.

ما هي خوارزمية QuickSort؟

الـ QuickSort هي خوارزمية فرز مقارنة (comparison-based sorting algorithm) بتقسم المصفوفة (array) لمجموعتين أصغر، ثم بتقوم بفرز كل مجموعة بشكل مستقل. الفكرة الرئيسية بتعتمد على اختيار عنصر محوري (pivot) من المصفوفة، ثم إعادة ترتيب العناصر بحيث تكون كل العناصر الأصغر من المحور على يساره، وكل العناصر الأكبر منه على يمينه. بعد هيك، بنكرر نفس العملية على المجموعتين الأصغر بشكل متكرر (recursive) لحتى نحصل على مصفوفة مرتبة.

كيف تعمل الـ QuickSort خطوة بخطوة؟

  1. اختيار المحور (Pivot Selection): بنختار عنصر من المصفوفة ليكون هو المحور. ممكن نختار العنصر الأول، أو الأخير، أو أي عنصر عشوائي.
  2. التقسيم (Partitioning): بنعيد ترتيب العناصر في المصفوفة بحيث تكون كل العناصر الأصغر من المحور على يساره، وكل العناصر الأكبر منه على يمينه.
  3. التكرار (Recursion): بنطبق نفس العملية (التقسيم والفرز) على المجموعتين الأصغر (المجموعة اللي على يسار المحور، والمجموعة اللي على يمينه) بشكل متكرر لحتى نحصل على مصفوفة مرتبة.

تحليل أداء QuickSort

أداء الـ QuickSort بيعتمد بشكل كبير على كيفية اختيار المحور. في أفضل الحالات (best case) والحالات المتوسطة (average case)، بيكون الأداء O(n log n)، بينما في أسوأ الحالات (worst case) بيكون الأداء O(n^2).

  • أفضل الحالات (Best Case): بيحدث لما نختار المحور بحيث يقسم المصفوفة لمجموعتين متساويتين تقريباً في كل مرة.
  • الحالات المتوسطة (Average Case): بيحدث لما نختار المحور بشكل عشوائي، أو لما يكون توزيع البيانات في المصفوفة عشوائي.
  • أسوأ الحالات (Worst Case): بيحدث لما نختار المحور بحيث يكون هو أصغر أو أكبر عنصر في المصفوفة في كل مرة. في هالحالة، بنضطر لفرز مصفوفة بحجم n-1 عنصر في كل مرة، مما يؤدي لأداء O(n^2).

نصيحة من أبو عمر: حاول دائماً تختار المحور بشكل عشوائي، أو استخدم طريقة “Median-of-Three” لاختيار المحور. هاي الطرق بتقلل بشكل كبير من احتمالية الوصول لأسوأ الحالات.

تطبيق QuickSort في بايثون

هاد مثال كود بسيط لتطبيق QuickSort في بايثون:


def quicksort(arr):
  if len(arr) <= 1:
    return arr
  pivot = arr[len(arr) // 2]
  left = [x for x in arr if x  pivot]
  return quicksort(left) + middle + quicksort(right)

# مثال للاستخدام
arr = [3, 6, 8, 10, 1, 2, 1]
sorted_arr = quicksort(arr)
print("Sorted array:", sorted_arr) # Output: Sorted array: [1, 1, 2, 3, 6, 8, 10]

تطبيق QuickSort في جافا

وهاد مثال كود مماثل لتطبيق QuickSort في جافا:


public class QuickSort {

    public static 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);
        }
    }

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

        for (int j = low; j <= high - 1; j++) {
            if (arr[j] < pivot) {
                i++;
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        return (i + 1);
    }

    public static void main(String[] args) {
        int[] arr = {3, 6, 8, 10, 1, 2, 1};
        quickSort(arr, 0, arr.length - 1);

        System.out.print("Sorted array: ");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        // Output: Sorted array: 1 1 2 3 6 8 10
    }
}

نصائح لتحسين أداء QuickSort

هون بعض النصائح اللي ممكن تساعدك لتحسين أداء الـ QuickSort:

  • اختيار المحور العشوائي (Random Pivot Selection): زي ما ذكرت قبل، اختيار المحور بشكل عشوائي بيقلل من احتمالية الوصول لأسوأ الحالات.
  • استخدام Insertion Sort للمصفوفات الصغيرة: الـ Insertion Sort بيكون أسرع من الـ QuickSort للمصفوفات الصغيرة. ممكن تستخدم الـ Insertion Sort لما يكون حجم المصفوفة أقل من قيمة معينة (مثلاً 10 أو 20 عنصر).
  • تحسين عملية التقسيم (Partitioning Optimization): ممكن تحسن عملية التقسيم عن طريق استخدام تقنيات مثل Hoare’s Partitioning Scheme.

الخلاصة: QuickSort صديقك في عالم الفرز!

الـ QuickSort هي خوارزمية فرز قوية وفعالة، وبتعتبر من الأدوات الأساسية اللي لازم تكون موجودة في جعبة كل مبرمج. تعلمناها اليوم، وحللنا أدائها، وطبقناها عملياً في بايثون وجافا. بتمنى تكون هالمقالة فادتكم، وإذا عندكم أي سؤال، لا تترددوا تسألوا. 👍

نصيحة أخيرة من أبو عمر: لا تخاف تجرب وتعدل على الكود. البرمجة تعلم بالممارسة والتجربة. حاول تطبق الـ QuickSort على مشاكل مختلفة، وشوف كيف ممكن تحسن أدائها. بالتوفيق! 🚀

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

​معمارية البرمجيات

تغيير قاعدة البيانات كان يتطلب إعادة كتابة نصف التطبيق: كيف أنقذتني ‘المعمارية النظيفة’ (Clean Architecture) من هذا الكابوس؟

أشارككم قصة حقيقية من مسيرتي كمبرمج، حيث كاد قرار تغيير قاعدة البيانات أن يدمر مشروعًا بالكامل. سأشرح لكم كيف أنقذتني مبادئ "المعمارية النظيفة" (Clean Architecture)...

19 مارس، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كل زر بلون مختلف وكل أيقونة بقصة: كيف أنقذني ‘نظام التصميم’ (Design System) من فوضى الواجهات؟

أشارككم قصة من قلب المعركة، كيف انتقلنا من فوضى الألوان والأزرار المتضاربة في مشاريعنا إلى التناغم والكفاءة. هذه المقالة هي دليلك العملي لفهم وبناء "نظام...

18 مارس، 2026 قراءة المزيد
الحوسبة السحابية

كل نقرة في لوحة التحكم كانت قنبلة موقوتة: كيف أنقذتني ‘البنية التحتية كشيفرة’ (IaC) من كارثة محققة؟

أشارككم قصة حقيقية عن كارثة كادت أن تدمر مشروعاً كاملاً بسبب نقرة خاطئة في لوحة التحكم السحابية. اكتشفوا كيف أنقذتني منهجية "البنية التحتية كشيفرة" (IaC)...

17 مارس، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

مقابلاتي السلوكية كانت كارثة: كيف أنقذتني طريقة STAR من أسئلة ‘حدثنا عن موقف صعب…؟’

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

16 مارس، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

خدمة واحدة بطيئة شلّت النظام بأكمله: كيف أنقذني نمط ‘قاطع الدائرة’ (Circuit Breaker) من تأثير الدومينو؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، حيث كادت خدمة واحدة بطيئة أن تُسقط نظامنا بالكامل. سأشرح لكم بالتفصيل نمط "قاطع الدائرة" (Circuit Breaker)، وكيف...

16 مارس، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

كنا نخزن بطاقات الائتمان مباشرة… قصة تسريب بيانات وكيف أنقذني الترميز (Tokenization)

أشارككم قصة حقيقية من بداياتي في عالم التكنولوجيا المالية، حين كاد خطأ بسيط في تخزين بيانات بطاقات الائتمان أن يدمر شركتنا. اكتشفوا كيف كانت تقنية...

15 مارس، 2026 قراءة المزيد
البودكاست