نظرة عامة على الخوارزمية
يعتمد فرز الدمج على استراتيجية تسمى "Divide and Casher". الفكرة الأساسية هي كما يلي:
1. لمصفوفتين مطلوبتين ، لدمجهما في صفيف مرتبة ، يمكننا بسهولة كتابة الرمز التالي:
// كلا A و B هو Ascend.public void merge (int [] a ، int [] b ، int [] c) {int i = 0 ، j = 0 ، k = 0 ؛ بينما (i <= a.length && j <= b.length) {if (a [i] <= b [i]) {c [k ++] = a [i ++] ؛ } آخر {c [k ++] = b [j ++] ؛ }} بينما (i <= a.length) {c [k ++] = a [i ++] ؛ }} من السهل أن نرى أن خوارزمية الدمج هذه فعالة ويمكن أن تصل تعقيد الوقت إلى O (n).
2. إذا كان هناك صفيف غير مرتبة يجب فرزه ، ولكن يتم طلب اثنين من الطوائف الفرعية A و B بشكل منفصل ، يمكننا أيضًا تنفيذها بسهولة بمساعدة الكود أعلاه ؛
3. إذن ، ماذا علي أن أفعل إذا تم اضطراب A و B؟ يمكنك تقسيمها إلى صفائف أصغر.
4. إذا قمت بتقسيمها إلى أصغرها ، فإن كل مسجل فرعي لديه عنصر واحد فقط ، يمكن اعتباره صفيفًا مرتبة.
5. ابدأ بهذه المصفوفات الأصغر ، ودمجها على الخطوات المذكورة أعلاه ، ويتم ترتيب الصفيف بأكمله.
باختصار ، يتم فرز الدمج هو استخدام العودية ، وتحلل المصفوفة أولاً إلى جهاز فرعي ، ثم دمج الصفيف.
مثال
هنا مثال. إذا كنت ترغب في فرز الصفيف A = {2،1،3،5،2،3} ، فقسس الصفيف إلى اثنين من الطوائف الفرعية: {2،1،3} و {5،2،3}. بعد فرز هاتين المصفوفتين الفرعيتين ، يصبحون {1،2،3} و {2،3،5} ، ثم دمج المصفوفتين للحصول على المصفوفة النهائية المطلوبة. تطبيق الكود كما يلي:
void sort (int [] a) {int [] aux = new int [A.Length] ؛ // aux array mergesort (a ، 0 ، a.length - 1 ، aux) ؛} void mergesort (int [] a ، int lo ، int hi ، int [] aux) {if (hi <= lo) return ؛ int mid = lo + (hi - lo) / 2 ؛ Mergesort (a ، lo ، mid ، aux) ؛ mergesort (a ، mid + 1 ، hi ، aux) ؛ Merge (a ، lo ، mid ، hi ، aux) ؛} proid merge (int [] a ، int lo ، int mid ، int hi ، int [] aux) {int i = lo ، j = mid + 1 ؛ لـ (int k = lo ؛ k <= hi ؛ k ++) {aux [k] = a [k] ؛ } لـ (int k = lo ؛ k <= hi ؛ k ++) {if (i> mid) a [k] = aux [j ++] ؛ آخر إذا (j> hi) a [k] = aux [i ++] ؛ آخر إذا (aux [i] <= aux [j]) a [k] = aux [i ++] ؛ آخر a [k] = aux [j ++] ؛ }} تطبيق آخر: فرز دمج من أسفل إلى أعلى
في التنفيذ أعلاه ، يعادل تقسيم مشكلة كبيرة إلى مشاكل صغيرة وحلها بشكل منفصل ، ثم استخدام إجابات لجميع المشكلات الصغيرة لحل المشكلة الكبيرة بأكملها. تقسيم نوع مجموعة كبيرة إلى صفيف صغير ، يعد هذا النوع من النوع من أعلى إلى أسفل. هناك تطبيق آخر هو الفرز من أسفل إلى أعلى ، أي أول دمج اثنين ثم دمج أربعة وأربعة ... تنفيذ الكود كما يلي:
void sort (int [] a) {int n = A.Length ؛ int [] aux = new int [n] ؛ لـ (int sz = 1 ؛ sz <n ؛ sz + = sz) {for (int lo = 0 ؛ lo <n - sz ؛ lo + = sz + sz) {// في كل جولة من الدمج ، قد يكون العائق الفرعي الثاني الذي تم دمجه في المرة الأخيرة من المصلح الفرعي الأول (a ، l ، lo + sz - 1 ، math.min }}}