الترتيب بالإدراج
آخر تحديث
يبني الترتيب بالإدراج المصفوفة المرتبة عنصرًا واحدًا في كل مرة. يأخذ العنصر غير المرتب التالي ("المفتاح") ويزيح كل عنصر أكبر في المنطقة المرتبة خانة واحدة إلى اليمين، ثم يضع المفتاح في الفجوة. هذه هي بالضبط الطريقة التي يرتب بها معظم الناس أوراق اللعب في أيديهم. اضغط على تشغيل في الأعلى لمشاهدة كيفية إدراج كل مفتاح، أو تنقّل عبر عمليات الإزاحة واحدة تلو الأخرى.
الترتيب بالإدراج سريع جدًا على المدخلات الصغيرة أو شبه المرتبة - إذ يعمل في O(n) عندما تكون البيانات مرتبة بالفعل - ولهذا تلجأ إليه العديد من خوارزميات الترتيب الهجينة للمصفوفات الفرعية الصغيرة.
التعقيد الزمني والمكاني
| الحالة | التعقيد | ملاحظات |
|---|---|---|
| أفضل حالة | O(n) | مرتبة بالفعل |
| الحالة المتوسطة | O(n²) | ترتيب عشوائي |
| أسوأ حالة | O(n²) | مرتبة عكسيًا |
| المساحة | O(1) | في المكان |
| مستقر | نعم | العناصر المتساوية تحتفظ بترتيبها النسبي |
خطوة بخطوة
| الخطوة | ماذا يحدث |
|---|---|
| 1 | اعتبر العنصر الأول منطقة مرتبة بحجم واحد. |
| 2 | خذ العنصر التالي كمفتاح. |
| 3 | أزح كل عنصر مرتب أكبر من المفتاح خانة واحدة إلى اليمين. |
| 4 | أدرج المفتاح في الفجوة المفتوحة. |
| 5 | كرر حتى يتم إدراج كل عنصر. |
مثال محلول
ترتيب [5, 2, 4, 1]:
| التمريرة | المصفوفة | الإجراء |
|---|---|---|
| البداية | [5, 2, 4, 1] | 5 هي المنطقة المرتبة الأولية بحجم واحد. |
| 1 | [2, 5, 4, 1] | المفتاح 2: أزح 5 إلى اليمين، أدرج 2 في المقدمة. |
| 2 | [2, 4, 5, 1] | المفتاح 4: أزح 5 إلى اليمين، 2 أصغر فتوقف، أدرج 4. |
| 3 | [1, 2, 4, 5] | المفتاح 1: أزح 5 و4 و2 إلى اليمين، أدرج 1 في المقدمة. |
| انتهى | [1, 2, 4, 5] | تم إدراج كل العناصر؛ المصفوفة مرتبة. |
متى تستخدم الترتيب بالإدراج
| استخدمه عندما | تجنّبه عندما |
|---|---|
تكون المصفوفة صغيرة (تقريبًا n < 20). | تكون المصفوفة كبيرة ومرتبة عشوائيًا. |
تكون البيانات شبه مرتبة بالفعل، مما يعطي أفضل حالة O(n). | تحتاج إلى أسوأ حالة مضمونة بـ O(n log n). |
تحتاج إلى ترتيب مستقر في المكان بمساحة إضافية O(1). | يكون نقل العناصر مكلفًا، لأنه يجري الكثير من عمليات الإزاحة. |
| تصل البيانات تدريجيًا ويجب أن تبقى مرتبة بشكل متصل. | يكون الإدخال مرتبًا عكسيًا، وهي أسوأ حالة O(n²). |
كود Insertion Sort
تنفيذ نظيف وقابل للتشغيل لخوارزمية Insertion Sort بلغات Python, JavaScript, Java, C++, C. اختر لغة، وانسخ الكود، أو افتحه محمّلًا مسبقًا في ساحة تجربة Coddy.
كود Insertion Sort بلغة Python
1def insertion_sort(a):2 for i in range(1, len(a)):3 key = a[i]4 j = i - 15 # Shift larger elements one slot to the right6 while j >= 0 and a[j] > key:7 a[j + 1] = a[j]8 j -= 19 a[j + 1] = key10 return a11
12
13nums = [7, 3, 9, 1, 5, 8, 2]14print("Before:", nums)15insertion_sort(nums)16print("After: ", nums)كود Insertion Sort بلغة JavaScript
1function insertionSort(a) {2 for (let i = 1; i < a.length; i++) {3 const key = a[i];4 let j = i - 1;5 // Shift larger elements right to open a slot for key6 while (j >= 0 && a[j] > key) {7 a[j + 1] = a[j];8 j--;9 }10 a[j + 1] = key;11 }12 return a;13}14
15const data = [5, 2, 9, 1, 7, 3];16console.log("Before:", data);17console.log("Sorted:", insertionSort([...data]));كود Insertion Sort بلغة Java
1import java.util.Arrays;2
3public class Main {4 static void insertionSort(int[] arr) {5 for (int i = 1; i < arr.length; i++) {6 int key = arr[i];7 int j = i - 1;8 // Shift larger elements one slot to the right9 while (j >= 0 && arr[j] > key) {10 arr[j + 1] = arr[j];11 j--;12 }13 arr[j + 1] = key;14 }15 }16
17 public static void main(String[] args) {18 int[] arr = {7, 3, 9, 1, 5, 8, 2};19 System.out.println("Before: " + Arrays.toString(arr));20 insertionSort(arr);21 System.out.println("After: " + Arrays.toString(arr));22 }23}كود Insertion Sort بلغة C++
1#include <iostream>2#include <vector>3
4void printVec(const std::vector<int>& a) {5 for (int x : a) std::cout << x << " ";6 std::cout << "\n";7}8
9void insertionSort(std::vector<int>& a) {10 for (size_t i = 1; i < a.size(); ++i) {11 int key = a[i];12 int j = static_cast<int>(i) - 1;13 // Shift larger elements one slot to the right14 while (j >= 0 && a[j] > key) {15 a[j + 1] = a[j];16 --j;17 }18 a[j + 1] = key;19 }20}21
22int main() {23 std::vector<int> data = {7, 3, 9, 1, 5, 8, 2};24 std::cout << "Before: ";25 printVec(data);26 insertionSort(data);27 std::cout << "After: ";28 printVec(data);29 return 0;30}كود Insertion Sort بلغة C
1#include <stdio.h>2
3void printArr(const int a[], int n) {4 for (int i = 0; i < n; i++) printf("%d ", a[i]);5 printf("\n");6}7
8void insertionSort(int a[], int n) {9 for (int i = 1; i < n; i++) {10 int key = a[i];11 int j = i - 1;12 // Shift larger elements one slot to the right13 while (j >= 0 && a[j] > key) {14 a[j + 1] = a[j];15 j--;16 }17 a[j + 1] = key;18 }19}20
21int main(void) {22 int data[] = {7, 3, 9, 1, 5, 8, 2};23 int n = sizeof(data) / sizeof(data[0]);24 printf("Before: ");25 printArr(data, n);26 insertionSort(data, n);27 printf("After: ");28 printArr(data, n);29 return 0;30}الأسئلة الشائعة حول الترتيب بالإدراج
ما هو التعقيد الزمني للترتيب بالإدراج؟
O(n²) في المتوسط وفي أسوأ الحالات، لكنه O(n) على مصفوفة مرتبة بالفعل أو شبه مرتبة. يستخدم مساحة إضافية O(1).هل الترتيب بالإدراج مستقر؟
متى ينبغي أن أستخدم الترتيب بالإدراج؟
ما الفرق بين الترتيب بالإدراج والترتيب الفقاعي؟
O(n²)، لكن الترتيب بالإدراج يزيح العناصر لفتح فجوة للمفتاح، بينما يبدّل الترتيب الفقاعي مرارًا الأزواج المتجاورة غير المرتبة. عادةً ما يجري الترتيب بالإدراج عمليات كتابة أقل ويؤدي أداءً أفضل عمليًا، خصوصًا على البيانات شبه المرتبة حيث يبلغ أفضل حالة O(n).لماذا يكون الترتيب بالإدراج أسرع من الترتيب بالدمج على المصفوفات الصغيرة؟
O(n log n) على المدخلات الصغيرة رغم تعقيده المقارب الأسوأ. لهذا السبب بالذات تتحول خوارزميات الترتيب الهجينة مثل Timsort وintrosort إلى الترتيب بالإدراج للمصفوفات الفرعية الصغيرة.هل يعمل الترتيب بالإدراج بشكل أفضل مع قائمة مترابطة أم مع مصفوفة؟
O(n²).