النوع السريع العادي
ابحث عن قاعدة قيمة قاعدة ، ثم قم بفرزها في رحلة واحدة بحيث تكون الأرقام الموجودة على يسار القاعدة أصغر من القاعدة ، والأرقام الموجودة على يمين القاعدة أكبر من أو تساوي القاعدة. ثم قسّمها إلى فرزين فرزتين. عودية مثل هذا.
الطبقة العامة QuickSort {public static <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr) {sort (arr ، 0 ، arr.length - 1) ؛} ثابت عام <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr ، int int ، int int) {if (left> = right) return ؛ int p = partition (arr ، يسار ، يمين) ؛ الفرز (arr ، يسار ، p - 1) ؛ فرز (arr ، p + 1 ، يمين) ؛} static private <t يمتد قابلة للمقارنة <؟ super t >> int partition (t [] arr ، int int ، int right) {t base = arr [left] ؛ int j = left ؛ for (int i = left+1 ؛ i <= ritle ؛ i ++) {if (base.compareto (arr [i])> 0) {j ++ ؛ swap (arr ، j ، i) ؛ SORTING} تبديل الفراغ الثابت العام (Object [] arr ، int i ، int j) {if (i! = j) {object temp = arr [i] ؛ arr [i] = arr [j] ؛ {system.out.print (o) ؛ system.out.print ("/t") ؛} system.out.println () ؛ 6sort (arr) ؛ printarr (arr) ؛ // 0 1 2 3 4 5 6 7 8 9}}التحسين السريع للفرز: حدد قاعدة القيمة الأساسية بشكل عشوائي
عندما يتم ترتيب الصفيف تقريبًا ، يكون أداء الترتيب السريع ضعيفًا (لأنه بعد كل طلب ، يكون الحجم العودية للغواصات اليمنى واليسرى مختلفًا تمامًا ، ومن المرجح أن يصل الجزء الأكبر إلى O (n^2) في النهاية).
الحل: يتم تحديد القيمة المرجعية بشكل عشوائي ، بدلاً من أخذ الرقم الأول في كل مرة. لن ينزعج هذا من "المصفوفات التي تم طلبها تقريبًا". لكن أداء الفرز لـ "المصفوفات خارج الترتيب تقريبًا" قد ينخفض قليلاً ، على الأقل هناك المزيد من الجزء الذي يتم تبديله قبل الفرز. هذا التبادل لا معنى له في الخارج ... هناك العديد من مكونات "الحظ" ...
الطبقة العامة QuickSort {public static <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr) {sort (arr ، 0 ، arr.length - 1) ؛} ثابت عام <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr ، int int ، int int) {if (left> = right) return ؛ int p = partition (arr ، يسار ، يمين) ؛ الفرز (arr ، يسار ، p - 1) ؛ فرز (arr ، p + 1 ، يمين) ؛} static private <t يمتد قابلة للمقارنة <؟ super t >> int partition (t [] arr ، int left ، int right) {// قبل الفرز ، دع القيمة المرجعية يتم تبادلها برقم عشوائي. بهذه الطريقة ، القيمة المرجعية عشوائية. // لن يتسبب ذلك في عدم اتساق المقياس المتكرر للجانبين اليسرى واليمين عندما يتم ترتيب الصفيف نسبيًا ، مما يؤدي إلى أسوأ مبادلة التعقيد الزمني (arr ، يسار ، (int) (math.random ()* (base.compareto (arr [i])> 0) {j ++ ؛ swap (arr ، j ، i) ؛}} swap (arr ، arr ، j) ؛ return j ؛ temp ؛}} private static void printarr (object [] arr) {for (object o: arr) {system.out.print (o) ؛ system.out.print ("/t") ؛} system.out.println () ؛} public static void main (string args [] {integer [] arr = {3 ، 5 ، 1 ، 2 ، 2 ، 0 ، 0 ، 0 ، 0 ، 4 6} ؛ printarr (arr) ؛ // 3 5 1 7 2 9 8 0 4 6sort (arr) ؛ printarr (arr) ؛ // 0 1 2 3 4 5 6 7 8 9}}يستمر الفرز السريع في التحسين: استخدم Insert Forting بالاقتران
الترتيب السريع هو تقليل حجم المشكلة باستمرار لحل المشكلات الفرعية ويتطلب عودة مستمرة. ومع ذلك ، فإن العودية صغيرة بما يكفي ، وإذا استمر تنفيذ هذا التكرار غير المستقر ، فقد لا تكون الكفاءة جيدة جدًا.
لذلك عندما تكون المشكلة صغيرة ومنظمة تقريبًا ، فإن فرز الإدراج يعمل بشكل جيد. يمكنك في كثير من الأحيان رؤية مثل هذه التعليقات في المصفوفات.
الطبقة العامة QuickSort {public static <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr) {sort (arr ، 0 ، arr.length - 1 ، 16) ؛}/*** @param arr array ليتم فرزه* param إغلاق اليسار* @param إغلاق اليمين* param k عند التكرار السريع للفرز السريع من المقياس الفرعي <= k ، إدراج فرز التحسين يتم استخدامه* param < يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr ، int int ، int int ، int k) {// يتم فرز ساعات المقياس عن طريق الإدراج إذا (يمين - يسار <= k) {insertionsort (arr ، يسار ، يمين) ؛ return ؛} int p = partition (arr ، arr ، يمين) ؛ super t >> insertionsortsort (t [] arr ، int l ، int r) {for (int i = l + 1 ؛ i <= r ؛ i ++) {t cur = arr [i] ؛ int j = i-1 ؛ for (؛ j> = 0 && cur.compareto (arr [j]) <0 ؛ j-) <t يمتد قابلة للمقارنة <؟ super t >> int partition (t [] arr ، int left ، int right) {// قبل الفرز ، اترك تبادل القيمة المرجعية برقم عشوائي. بهذه الطريقة ، القيمة المرجعية عشوائية. // لن يتسبب ذلك في عدم اتساق المقياس المتكرر للجوانب اليمنى واليسرى عندما يكون الصفيف ترتيبًا نسبيًا ، مما يؤدي إلى أسوأ مبادلة التعقيد الزمني (ARR ، يسار ، (int) (Math.Random () * > 0) {j ++ ؛ swap (arr ، j ، i) ؛}} swap (arr ، يسار ، ي) printarr (object [] arr) {for (object o: arr) {system.out.print (o) ؛ system.out.print ("/t") ؛} system.out.println () ؛} public static void main (string args []) 0 4 6SORT (ARR) ؛ PRINTARR (ARR) ؛ // 0 1 2 3 4 5 6 7 8 9}}يستمر الفرز السريع في التحسين: فرز سريع في اتجاهين
في الفرز السريع الأولي الطبيعي ، يُقال أن القيمة الأساسية على الجانب الأيسر من القاعدة أصغر من القاعدة ، في حين أن القاعدة على الجانب الأيمن أكبر من أو تساوي القاعدة. هذه تساوي القاعدة سوف تتجمع إلى اليمين (أو تغيير علاقة الحجم قليلاً سوف تتجمع إلى اليسار). على أي حال ، سوف يجتمع جانبا. عندما يتم تكرار العديد من الأرقام في الصفيف ، فإن ذلك سيؤدي إلى اختلاف كبير في حجم الغواصين. في هذا الوقت ، أود تعيين الأرقام المساوية للقاعدة على جانبي القاعدة ، بدلاً من جمعها معًا.
(ملاحظة: عند اختبار الرمز ، من الأفضل أن ننظر بعيدًا عن جزء من نوع الإدراج وتبدو في الكود الخاص بي أدناه ... وإلا ، عندما يكون حجم البيانات أقل من K = 16 ، يتم تنفيذ نوع الإدراج ...)
الطبقة العامة QuickSort {public static <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr) {sort (arr ، 0 ، arr.length - 1 ، 16) ؛}/*** @param arr array ليتم فرزه* param إغلاق اليسار* @param إغلاق اليمين* param k عند التكرار السريع للفرز السريع من المقياس الفرعي <= k ، إدراج فرز التحسين يتم استخدامه* param < يمتد قابلة للمقارنة <؟ Super t >> فرز void (t [] arr ، int int ، int int ، int k) {// insertionsort (arr ، يسار ، يمين) ؛ // return ؛ //} if (left> = return) return ؛ int p = partition (arr ، يسار ، يمين) ؛ اليسار ، اليسار ، اليمين) ؛ super t >> insertionsortsort (t [] arr ، int l ، int r) {for (int i = l + 1 ؛ i <= r ؛ i ++) {t cur = arr [i] ؛ int j = i-1 ؛ for (؛ j> = 0 && cur.compareto (arr [j]) <0 ؛ j-) <t يمتد قابلة للمقارنة <؟ super t >> int partition (t [] arr ، int left ، int right) {// قبل الفرز ، اترك تبادل القيمة المرجعية برقم عشوائي. بهذه الطريقة ، القيمة المرجعية عشوائية. // لن يتسبب في عدم اتساق المقاييس العودية للجانبين اليسرى واليسرى عندما يتم ترتيب الصفيف نسبيًا ، مما يؤدي إلى أسوأ مبادلة التعقيد في الوقت (ARR ، يسار ، (int) (Math.Random () * (اليمين - يسار + 1) + يسار) +1 ؛ // للمادة [اليسار+1 ......... اليمين] المذكورة في السطر السابق ، أقصد [اليسار+1 ...... i) الفاصل الزمني الأيسر المغلقة على اليمين أقل من أو يساوي القاعدة. int j = يمين ؛ // بالنسبة للفاصل الزمني [الأيسر+1 ...... اليمين] المذكورة في الخطين السابقين ، j يعني أن قيم (j ...... اليمين] الفواصل الزمنية المفتوحة واليسرى أكبر من أو تساوي القاعدة. خارج العنصر الأول أصغر من القاعدة ، ثم يتوقف j هناك. مبادلة الفراغ الثابت (Object [] arr ، int i ، int j) {if (i! = j) {object temp = arr [i] ؛ arr [i] = arr [j] ؛ arr [j] = temp ؛}} printarr printarr static static الخاص (كائن [] arr) {for (orb) {system.out.print (o) ؛ system.out.print ("/t") ؛} system.out.println () ؛ 6sort (arr) ؛ printarr (arr) ؛ // 0 1 2 3 4 5 6 7 8 9}}استمر في تحسين الفرز السريع: فرزان سريعان لا يتطلب مبادلة ، استخدم التبادل
عندما يجد المساران أعلاه قيمًا أكبر من القاعدة والقيم أقل من القاعدة ، فإنها تستخدم طريقة المبادلة () للتبادل. يتضمن التبادل المكون من رقمين تشغيل درجة الحرارة المتغيرة الثالثة ، مع المزيد من عمليات القراءة والكتابة. بعد ذلك ، استخدم طريقة المهمة المباشرة لوضع أقل من اليمين وأكبر من اليسار. عندما ألتقي ، هذا الموقف هو المكان الذي يجب أن توضع فيه القاعدة. تم الانتهاء من هذه الرحلة. مجرد إعادة.
الطبقة العامة QuickSort {public static <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr) {sort (arr ، 0 ، arr.length - 1 ، 16) ؛}/*** @param arr array ليتم فرزه* param إغلاق اليسار* @param إغلاق اليمين* param k عند التكرار السريع للفرز السريع من المقياس الفرعي <= k ، إدراج فرز التحسين يتم استخدامه* param < يمتد قابلة للمقارنة <؟ Super t >> فرز void (t [] arr ، int int ، int int ، int k) {// insertionsort (arr ، يسار ، يمين) ؛ // return ؛ //} if (left> = return) return ؛ int p = partition (arr ، يسار ، يمين) ؛ اليسار ، اليسار ، اليمين) ؛ super t >> insertionsortsort (t [] arr ، int l ، int r) {for (int i = l + 1 ؛ i <= r ؛ i ++) {t cur = arr [i] ؛ int j = i-1 ؛ for (؛ j> = 0 && cur.compareto (arr [j]) <0 ؛ j-) <t يمتد قابلة للمقارنة <؟ super t >> int partition (t [] arr ، int left ، int right) {// قبل الفرز ، اترك تبادل القيمة المرجعية برقم عشوائي. بهذه الطريقة ، القيمة المرجعية عشوائية. // لن يتسبب ذلك في أن تكون المقاييس العودية للجوانب اليمنى واليسرى غير متسقة عندما يتم ترتيب الصفيف نسبيًا ، مما يؤدي إلى أسوأ تبديل التعقيد في الوقت (ARR ، يسار ، (int) (Math.Random () * (اليمين-يسار + 1) = يسار ؛ // للتراجع [اليسار+1 ......... اليمين] المذكورة في السطر السابق ، يعني [اليسار+1 ...... i) قيم الفاصل الزمني المغلقة اليسرى أقل من أو تساوي القاعدة. int j = يمين ؛ // بالنسبة للفاصل الزمني [الأيسر+1 ...... اليمين] المذكورة في الخطين السابقين ، j يعني أن قيم (j ...... يمين] الفواصل الفتحة اليسرى والمنتجة اليمنى أكبر من أو تساوي القاعدة. arr [j] ؛ // مسح من اليسار إلى اليمين ، قم بفحص العنصر الأول أكبر من القاعدة ، ثم أتوقف هناك. ! = j) {object temp = arr [i] ؛ arr [i] = arr [j] ؛ arr [j] = temp ؛}} printarr printarr static static static (object [] arr) {for (object o: arr) {system.out.print (o) ؛ system.out.print ("/t") ؛ = {3 ، 5 ، 1 ، 7 ، 2 ، 9 ، 8 ، 0 ، 4 ، 6} ؛ printarr (arr) ؛ // 3 5 1 7 2 9 8 0 4 6sort (arr) ؛ printarr (arr) ؛ // 0 1 2 3 4 5 6 7 8 9}}يستمر الفرز السريع في التحسين: عند استخدام كمية كبيرة من البيانات والعديد من التكرارات ، استخدم الفرز السريع ثلاثي الاتجاه
قسّم الصفيف إلى ثلاثة مسارات. المسار الأول أصغر من القاعدة ، والمسار الثاني يساوي القاعدة ، والمسار الثالث أكبر من القاعدة.
استخدم مؤشرًا للمسح الضوئي من الأمام إلى الخلف ، إذا:
1. الرقم الذي يشير إليه CUR أقل من القاعدة ، ثم: تبادل قيم ARR [cur] و arr [i] ، ثم i ++ ، cur ++.
2. الرقم الذي يشير إليه CUR يساوي القاعدة ، ثم: cur ++
3. الرقم الذي يشير إليه CUR أكبر من القاعدة ، ثم: تبادل قيم ARR [cur] و arr [j] ، ثم J--.
عندما يكون cur> j ، فهذا يعني أنه تم الانتهاء من المسارات الثلاثة.
الطبقة العامة QuickSort {public static <t يمتد قابلة للمقارنة <؟ super t >> فرز void (t [] arr) {sort (arr ، 0 ، arr.length - 1 ، 16) ؛}/*** @param arr array ليتم فرزه* param إغلاق اليسار* @param إغلاق اليمين* param k عند التكرار السريع للفرز السريع من المقياس الفرعي <= k ، إدراج فرز التحسين يتم استخدامه* param < يمتد قابلة للمقارنة <؟ Super t >> فرز void (t [] arr ، int int ، int int ، int k) {// insertionsort (arr ، arr ، refress) ؛ // return ؛ //} if (left> = return) return ؛ int [] ret = artition (arr ، ars ، refer) ؛ arr ، relect ، ret [0] ؛ k) ؛ sort ، ret [1] super t >> insertionsortsort (t [] arr ، int l ، int r) {for (int i = l + 1 ؛ i <= r ؛ i ++) {t cur = arr [i] ؛ int j = i-1 ؛ for (؛ j> = 0 && cur.compareto (arr [j]) <0 ؛ j-) * param arr array ليتم فرزه* param اليسار الحدود اليسرى للمصفوفة المراد فرزها* param اليمين الحدود اليمنى للمصفوفة المراد فرزها* param <T> generics* return*/private static <t يمتد قابلة للمقارنة <؟ super t >> int [] partition (t [] arr ، int left ، int right) {// قبل الفرز ، دع القيمة المرجعية يتم تبادلها برقم عشوائي. بهذه الطريقة ، القيمة المرجعية عشوائية. // لن يتسبب ذلك في عدم اتساق المقاييس العودية على الجانبين الأيسر واليسر تنقسم الصفوف إلى القنوات الثلاث التالية (الفواصل الزمنية) int i = left ؛ // اليسار يشير إلى أن [lleft ... يسار) الأرقام الموجودة في الفاصل الزمني الأيسر الأيسر الأيمن تكون أصغر من القاعدة int j = يمين ؛ (cur <= j) {if (arr [cur] .Compareto (base) == 0) {cur ++ ؛} آخر إذا (arr [cur] .Compareto (base) <0) {swap (arr ، cur ++ ، i ++) ؛} {swap (arr ، cur ، j-) ؛}} ولا تحتاج المشكلات الفرعية إلا إلى حل اليسار واليمين من I و J} مبادلة الفراغ الثابتة العامة (Object [] arr ، int i ، int j) {if (i! = j) {object temp = arr [i] ؛ arr [i] = arr [j] ؛ {system.out.print (o) ؛ system.out.print ("/t") ؛} system.out.println () ؛ 6sort (arr) ؛ printarr (arr) ؛ // 0 1 2 3 4 5 6 7 8 9}}لخص
ما سبق هو كل التفسير التفصيلي لتنفيذ برمجة Java رمز الفرز والتحسين السريع. آمل أن يكون ذلك مفيدًا للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!