خوارزمية فرز الإدراج باستخدام لغة C، C++, Java, Python أمثلة

⚡ ملخص ذكي

فرز الإدراج هو أسلوب فرز يعتمد على المقارنة، ويُنشئ قائمة مرتبة عنصرًا تلو الآخر. يتميز هذا الأسلوب بالاستقرار، والمرونة، وسهولة التطبيق، وهو مناسب تمامًا لمجموعات البيانات الصغيرة أو شبه المرتبة.

  • 📥 الفكرة الأساسية: تقوم خوارزمية فرز الإدراج باختيار كل عنصر وإزاحته إلى اليسار حتى يستقر في الموضع الصحيح داخل القائمة الفرعية التي تم فرزها بالفعل.
  • 🔁 إدراج Operaنشوئها: تعتمد الخوارزمية على عمليات تبديل متكررة مع اليسار، مما يؤدي إلى زيادة المنطقة المصنفة بمقدار عنصر واحد في كل دورة خارجية.
  • ⚡ تعقيد الوقت: أفضل الحالات تعمل في O(n) للبيانات المصنفة بالفعل، بينما تصل أسوأ الحالات والحالات المتوسطة إلى O(n^2) للمدخلات المعكوسة أو المختلطة.
  • ✅ الخصائص: الخوارزمية متصلة بالإنترنت، وتعمل في مكانها، ومستقرة، وقابلة للتكيف، مما يجعلها قابلة للتنبؤ بالنسبة لعمليات الإدخال المتدفقة والمصفوفات المصنفة جزئيًا.
  • 🧪 Code تغطية: يتم توفير تطبيقات مرجعية بلغة C، C++و Python حتى يتمكن المتعلمون من مقارنة هياكل الحلقات وآليات التبديل جنبًا إلى جنب.
  • 🤖 زاوية الذكاء الاصطناعي: تقوم مساعدات الذكاء الاصطناعي الحديثة بتصور عمليات فرز الإدراج وتوصي بها عندما تكون مصفوفات الإدخال قصيرة أو مرتبة تقريبًا.

ما هو فرز الإدراج؟

يُعد فرز الإدراج أحد خوارزميات فرز المقارنة المستخدمة لفرز العناصر عن طريق التكرار على عنصر واحد في كل مرة ووضع العنصر في موضعه الصحيح داخل منطقة مرتبة بالفعل.

يُضاف كل عنصر بالتتابع إلى قائمة مُرتبة مسبقًا. حجم القائمة المُرتبة مسبقًا هو واحد في البداية. تضمن خوارزمية فرز الإدراج أن تكون العناصر k الأولى مُرتبة بعد التكرار k للحلقة الخارجية.

لأن فرز الإدراج يبني النتيجة بشكل تدريجي، فإنه من السهل تعليمه، وسهل تصحيحه، ويمثل أساسًا قويًا للمدخلات الصغيرة جدًا حيث تضيف الخوارزميات الأكثر تعقيدًا عبئًا إضافيًا دون مكاسب قابلة للقياس.

خصائص خوارزمية فرز الإدراج

تتميز خوارزمية فرز الإدراج بالخصائص المهمة التالية التي تفسر سلوكها في أحمال العمل الحقيقية:

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

مع وضع هذه السمات في الاعتبار، يشرح القسم التالي عملية الإدخال الأساسية التي تدعم كل دورة من دورات الخوارزمية.

كيف يتم إدراج Operaالعمل نشوئها؟

في خوارزمية فرز الإدراج، تُستخدم عملية الإدراج لفرز العناصر غير المرتبة. فهي تساعد على إدراج عنصر جديد في قائمة مرتبة مسبقًا مع الحفاظ على الترتيب الحالي للمنطقة المرتبة.

الشفرة الزائفة لعملية الإدراج:

النظر في قائمة A من العناصر N.

// Insert A[N-1] into sorted sublist A[0..N-2]
for i = N-1 to 1:
    if A[i] < A[i-1], then swap A[i] and A[i-1]
    else stop

إدراج Operaالعمل

في المثال أعلاه، يتم إدراج عنصر جديد رقم 6 في قائمة مرتبة مسبقًا. الخطوات التالية trace الحلقة الداخلية بينما ينتقل العنصر الجديد إلى اليسار نحو موضعه الصحيح.

الخطوة 1) بالمقارنة مع العنصر المجاور الأيسر لـ A[5]، 9 > 6، نقوم بتبديل الموضع 9 و6. الآن يتم نقل العنصر 6 إلى A[4].

الخطوة 2) الآن، نقارن A[4] و A[3]، ونجد أن A[3] > A[4]، لذلك نقوم مرة أخرى بتبديل موضع 6 و 8.

الخطوة 3) والآن قارن بين A[3] و A[2]. بما أن A[2] > A[3]، فإننا نبدل موضع الرقمين 7 و 6.

الخطوة 4) نقارن A[1] و A[2]. بما أن A[1] < A[2]، فإن العنصر المجاور الأيسر لم يعد أكبر. نستنتج أن 6 قد أُدخل بشكل صحيح، ونوقف الحلقة الداخلية هنا.

كيف يعمل فرز الإدراج

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

يعمل فرز الإدراج

يوضح الشكل أعلاه آلية عمل خوارزمية فرز الإدراج في بنية البيانات. في البداية، يوجد عنصر واحد فقط في القائمة الفرعية المرتبة، أي 4. بعد إدراج العنصر A[1]، أي 3، يزداد حجم القائمة الفرعية المرتبة إلى 2، وتستمر الخوارزمية في هذا النمط حتى يتم وضع جميع العناصر.

بعد وضع التدفق المفاهيمي، توضح الأقسام التالية تطبيقات عملية في C++، ج، و Python حتى تتمكن من مقارنة هياكل الحلقات عبر اللغات المختلفة.

C++ برنامج لفرز الإدراج

استخدم C++ يستخدم التنفيذ أدناه حلقتين متداخلتين: تقوم الحلقة الخارجية بتحديد العنصر غير المصنف التالي، وتقوم الحلقة الداخلية بتحريكه إلى اليسار حتى يتم العثور على الموضع الصحيح.

#include <iostream>
using namespace std;

int main(){
    //unsorted list
    int unsorted[] = {9,8,7,6,5,4,3,3,2,1};

    //size of list
    int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]);

    //printing unsorted list
    cout << "\nUnsorted: ";
    for(int i = 0 ; i < size_unsorted ; i++){
        cout << unsorted[i] << " ";
    }

    int current_element,temp;

    for(int i = 1; i < size_unsorted; i++){
        current_element = unsorted[i];
        for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){
            //swapping if current element is lesser
            temp = unsorted[j+1];
            unsorted[j+1] = unsorted[j];
            unsorted[j] = temp;
        }
    }

    //printing sorted list
    cout << "\nSorted: ";
    for(int i = 0 ; i < size_unsorted ; i++){
        cout << unsorted[i] << " ";
    }

    return 0;
}

الإخراج:

Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

C Code لفرز الإدراج

وينطبق المنطق نفسه مباشرة على لغة C. المعيار printf تستدعي هذه العملية مخرجات التدفق، لكن نمط التبديل داخل الحلقة الداخلية مطابق لـ C++ الإصدار.

#include <stdio.h>
int main() {
    //unsorted list
    int unsorted[] = {9,8,7,6,5,4,3,3,2,1};

    //size of list
    int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]);

    //printing unsorted list
    printf("\nUnsorted: ");
    for(int i = 0 ; i < size_unsorted ; i++){
        printf("%d ", unsorted[i]);
    }

    int current_element, temp;

    for(int i = 1; i < size_unsorted; i++){
        current_element = unsorted[i];
        for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){
            //swapping if current element is lesser
            temp = unsorted[j+1];
            unsorted[j+1] = unsorted[j];
            unsorted[j] = temp;
        }
    }

    //printing sorted list
    printf("\nSorted: ");
    for(int i = 0 ; i < size_unsorted ; i++){
        printf("%d ", unsorted[i]);
    }

    return 0;
}

الإخراج:

Output:
Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

Python برنامج لفرز الإدراج

Python يدعم تبديل الصفوفping في تعبير واحد، لذا فإن الحلقة الداخلية أكثر إيجازًا من حلقتها الأصلية. C++ نظائر مع الحفاظ على نفس السلوك الخوارزمي.

#unsorted list
unsorted = [9,8,7,6,5,4,3,3,2,1]

#size of list
size_unsorted = len(unsorted)

#printing unsorted list
print("\nUnsorted: ", end="")
for i in range(size_unsorted):
    print(unsorted[i], end=" ")

for i in range(1, size_unsorted):
    current_element = unsorted[i]
    j = i - 1
    while j >= 0 and unsorted[j] > current_element:
        #swapping if current element is lesser
        unsorted[j+1], unsorted[j] = unsorted[j], unsorted[j+1]
        j -= 1

#printing sorted list
print("\nSorted: ", end="")
for i in range(size_unsorted):
    print(unsorted[i], end=" ")

الإخراج:

Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

خصائص فرز الإدراج

فيما يلي خصائص مهمة لخوارزمية فرز الإدراج تساعدك على تحديد متى تكون الأداة المناسبة:

  • عبر الانترنت: تستطيع خوارزمية فرز الإدراج فرز العناصر فور استلامها. فإذا كنا قد فرزنا قائمة من العناصر مسبقًا وأضفنا إليها عناصر أخرى، فلا داعي لإعادة تنفيذ عملية الفرز بالكامل، بل نكتفي بتكرار العملية على العناصر المضافة حديثًا.
  • في المكان: تتميز خوارزمية فرز الإدراج بتعقيد مكاني ثابت ولا تتطلب مساحة إضافية. تقوم هذه الخوارزمية بفرز العناصر في مكانها.
  • مستقر: في خوارزمية فرز الإدراج، لا نبدل العناصر إذا كانت قيمها متساوية. على سبيل المثال، إذا كان العنصران x و y متساويين، وكان x يظهر قبل y في القائمة غير المرتبة، فسيظل x يظهر قبل y في القائمة المرتبة. وهذا ما يجعل خوارزمية فرز الإدراج مستقرة.
  • تكيفي: A خوارزمية الفرز تُعتبر خوارزمية فرز الإدراج تكيفية إذا استغرقت وقتًا أقل عندما تكون عناصر الإدخال أو مجموعة فرعية منها مُرتبة مسبقًا. وكما ذكرنا سابقًا، فإن أفضل وقت تشغيل لها هو O(N)، وأسوأ وقت تشغيل هو O(N²). تُعدّ خوارزمية فرز الإدراج إحدى خوارزميات الفرز التكيفية.

تعقيد فرز الإدراج

يتناول النقاش التالي حول التعقيد كلاً من استخدام الذاكرة ووقت التشغيل، مما يتيح لك مقارنة خوارزمية فرز الإدراج بالبدائل الأخرى مثل: Bubblه فرز و فرز سريع.

تعقيد الفضاء

لا تتطلب خوارزمية فرز الإدراج مساحة إضافية لفرز العناصر. فتعقيد المساحة ثابت، أي O(1)، لأنه لا يتم استخدام سوى عدد قليل من المتغيرات المؤقتة بغض النظر عن حجم المدخلات.

تعقيد الوقت

بما أن خوارزمية فرز الإدراج تُكرر العملية على عنصر واحد في كل مرة، فإنها تتطلب N-1 دورة لفرز N عنصرًا. في كل دورة، قد لا تُجري أي تبديلات إذا كانت العناصر مُرتبة بالفعل، أو قد تحتاج إلى العديد من التبديلات إذا كانت العناصر مُرتبة تنازليًا.

  • بالنسبة للتمرير 1، الحد الأدنى المطلوب للمقايضات هو صفر، والحد الأقصى للمقايضات المطلوبة هو 1.
  • بالنسبة للتمرير 2، الحد الأدنى المطلوب للمقايضات هو صفر، والحد الأقصى للمقايضات المطلوبة هو 2.
  • بالنسبة للتمرير N، الحد الأدنى المطلوب للمبادلة هو صفر، والحد الأقصى للمبادلة المطلوبة هو N.
  • الحد الأدنى للتبديل هو صفر، وبالتالي فإن أفضل تعقيد زمني هو O(N) لتكرار N تمريرة.
  • إجمالي عمليات التبديل القصوى هو (1+2+3+4+…+N) أي N(N+1)/2، لذا فإن أسوأ تعقيد زمني هو O(N^2).

فيما يلي أهم تعقيد زمني لخوارزمية فرز الإدراج:

  • أسوأ حالة تعقيدO(n^2): فرز مصفوفة بترتيب تنازلي عندما يكون المطلوب ترتيبها تصاعديًا هو أسوأ سيناريو.
  • أفضل تعقيد للحالة: O(n): أفضل حالة تحدث عندما تكون المصفوفة مرتبة بالفعل؛ حيث تُنفَّذ الحلقة الخارجية n مرة، بينما لا تُنفَّذ الحلقة الداخلية على الإطلاق. يوجد n مقارنة فقط، لذا فإن التعقيد خطي.
  • متوسط ​​تعقيد الحالة: O(n^2): يحدث هذا عندما تظهر عناصر المصفوفة بترتيب عشوائي ليس تصاعديًا ولا تنازليًا.

الأسئلة الشائعة

اختر خوارزمية فرز الإدراج للمصفوفات الصغيرة، أو البيانات شبه المرتبة، أو عمليات الإدراج المتدفقة حيث تصل العناصر الجديدة بعد فرز أولي. غالبًا ما تتفوق هذه الخوارزمية على الخوارزميات الأكثر تعقيدًا في هذه الحالات نظرًا لانخفاض تكلفتها الثابتة وسلوكها التكيفي.

نعم. خوارزمية فرز الإدراج مستقرة لأنها لا تبدل القيم المتساوية أبدًا، مما يحافظ على ترتيبها الأصلي. وهي أيضًا خوارزمية فرز مكانية لأنها تفرز باستخدام مصفوفة الإدخال فقط بالإضافة إلى عدد صغير وثابت من المتغيرات المؤقتة، مما يوفر مساحة إضافية ثابتة O(1).

أفضل الحالات هي O(n) عندما تكون المدخلات مرتبة مسبقًا، لأن الحلقة الداخلية لا تُنفذ أبدًا. أما أسوأ الحالات والحالات المتوسطة فهي O(n^2) عندما تكون المصفوفة معكوسة الترتيب أو مختلطة، وذلك بسبب الإزاحة المتكررة للعناصر نحو بداية المصفوفة.

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

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

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

تلخيص هذه التدوينة بـ: