دليل دراسة شامل
ترتيب الدمج هو خوارزمية ترتيب كلاسيكية تعتمد على استراتيجية "فرّق تسد" وكانت واحدة من أولى الخوارزميات التي حققت تعقيدًا زمنيًا O(N log N). تُعتبر واحدة من أفضل 10 خوارزميات في القرن العشرين في العلوم والهندسة.
المدخلات:
M E R G E S O R T E X A M P L E⬇️ بعد ترتيب النصف الأيسر ⬇️
⬇️ بعد ترتيب النصف الأيمن ⬇️
⬇️ بعد الدمج ⬇️
الهدف: إعطاء مصفوفتين فرعيتين مرتبتين a[lo] إلى a[mid] وa[mid+1] إلى a[hi]، استبدلهما بمصفوفة فرعية مرتبة واحدة a[lo] إلى a[hi].
مصفوفتان فرعيتان مرتبتان:
⬇️ بعد الدمج ⬇️
private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
// نسخ العناصر إلى المصفوفة المساعدة
for (int k = lo; k <= hi; k++)
aux[k] = a[k];
// الدمج مرة أخرى إلى المصفوفة الأصلية
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++]; // الجزء الأيسر نفد
else if (j > hi) a[k] = aux[i++]; // الجزء الأيمن نفد
else if (less(aux[j], aux[i])) a[k] = aux[j++]; // الجزء الأيمن أصغر
else a[k] = aux[i++]; // الجزء الأيسر أصغر أو مساوي
}
}
public class Merge {
private static void merge(...) { /* كما بالأعلى */ }
private static void sort(Comparable[] a, Comparable[] aux,
int lo, int hi) {
if (hi <= lo) return; // الحالة الأساسية
int mid = lo + (hi - lo) / 2; // إيجاد المنتصف
sort(a, aux, lo, mid); // ترتيب النصف الأيسر
sort(a, aux, mid + 1, hi); // ترتيب النصف الأيمن
merge(a, aux, lo, mid, hi); // دمج النتائج
}
public static void sort(Comparable[] a) {
Comparable[] aux = new Comparable[a.length];
sort(a, aux, 0, a.length - 1);
}
}
أفضل حالة، متوسط حالة، وأسوأ حالة
للمصفوفة المساعدة
الحد الأعلى
الحد الأعلى
علاقة التكرار:
T(N) = 2T(N/2) + N
| الحاسوب | ألف (10³) | مليون (10⁶) | مليار (10⁹) |
|---|---|---|---|
| منزلي (10⁸ مقارنة/ثانية) | لحظي | ثانية واحدة | 18 دقيقة |
| خارق (10¹² مقارنة/ثانية) | لحظي | لحظي | لحظي |
الخوارزميات الجيدة أفضل من الحواسيب الخارقة!
ترتيب الدمج على حاسوب منزلي يتفوق على ترتيب الإدراج (O(N²)) على حاسوب خارق للمجموعات الكبيرة.
بدلاً من تقسيم المصفوفة بشكل متكرر، ابدأ بمصفوفات فرعية صغيرة وادمجها بشكل تكراري.
public static void sort(Comparable[] a) {
int N = a.length;
Comparable[] aux = new Comparable[N];
// sz: حجم المصفوفات الفرعية للدمج (1, 2, 4, 8, ...)
for (int sz = 1; sz < N; sz = sz + sz) {
// lo: بداية المصفوفة الفرعية اليسرى
for (int lo = 0; lo < N - sz; lo += sz + sz) {
merge(a, aux, lo, lo + sz - 1,
Math.min(lo + sz + sz - 1, N - 1));
}
}
}
خوارزمية الترتيب مستقرة إذا حافظت على الترتيب النسبي للعناصر ذات المفاتيح المتساوية.
حالة استخدام نموذجية: الترتيب بمعايير متعددة
مع خوارزمية ترتيب مستقرة، يبقى الطلاب في نفس القسم مرتبين حسب الاسم!
| الاسم | القسم | بعد الترتيب حسب القسم (مستقر) |
|---|---|---|
| Andrews | 3 | Andrews (3) ← لا يزال مرتبًا! |
| Chen | 3 | Chen (3) ← لا يزال مرتبًا! |
| Fox | 3 | Fox (3) ← لا يزال مرتبًا! |
الفكرة الرئيسية: عملية الدمج تأخذ من المصفوفة الفرعية اليسرى عندما تكون المفاتيح متساوية.
if (less(aux[j], aux[i])) a[k] = aux[j++];
else a[k] = aux[i++]; // تأخذ من اليسار إذا تساوت
| الخوارزمية | مستقر؟ | السبب |
|---|---|---|
| ترتيب الإدراج | ✓ نعم | العناصر المتساوية لا تتحرك بعد بعضها |
| ترتيب الاختيار | ✗ لا | التبادلات بعيدة المدى قد تحرك العناصر المتساوية |
| ترتيب الدمج | ✓ نعم | عملية الدمج تحافظ على الترتيب |
| ترتيب شيل | ✗ لا | تبادلات بعيدة المدى |
المقارن هو واجهة في جافا تسمح لك بتحديد منطق مقارنة مخصص، منفصل عن الترتيب الطبيعي للنوع.
| Comparable | Comparator |
|---|---|
| ترتيب طبيعي (جزء من الفئة) | ترتيب بديل (فئة منفصلة) |
طريقة compareTo() |
طريقة compare() |
| ترتيب واحد لكل فئة | ترتيبات متعددة ممكنة |
Arrays.sort(array) |
Arrays.sort(array, comparator) |
public class Student {
private final String name;
private final int section;
// مقارن للترتيب حسب الاسم
public static class ByName implements Comparator<Student> {
public int compare(Student v, Student w) {
return v.name.compareTo(w.name);
}
}
// مقارن للترتيب حسب القسم
public static class BySection implements Comparator<Student> {
public int compare(Student v, Student w) {
return v.section - w.section;
}
}
}
// الاستخدام:
Arrays.sort(students, new Student.ByName());
Arrays.sort(students, new Student.BySection());
| نوع الترتيب | مثال |
|---|---|
| طبيعي | Now is the time |
| غير حساس لحالة الأحرف | is Now the time |
| إسباني | café cafetero churro cuarto nube ñoño |
| دليل الهاتف البريطاني | McKinley Mackintosh |
| الخوارزمية | في نفس المكان؟ | مستقر؟ | أفضل | متوسط | أسوأ | ملاحظات |
|---|---|---|---|---|---|---|
| ترتيب الاختيار | ✓ | ✗ | ½N² | ½N² | ½N² | N تبادل |
| ترتيب الإدراج | ✓ | ✓ | N | ¼N² | ½N² | استخدم لـ N صغيرة أو مرتبة جزئيًا |
| ترتيب شيل | ✓ | ✗ | N log N | ؟ | N^(3/2) | كود مضغوط؛ تحت تربيعي |
| ترتيب الدمج | ✗ | ✓ | ½N log N | N log N | N log N | ضمان N log N؛ مستقر |
Arrays.sort() في جافا للكائنات