国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

Java使用DualPivotQuicksort排序

瀏覽:68日期:2022-08-14 16:57:05
Java排序 - DualPivotQuicksort

這里描述 leftmost = true 的情況,也就是會從數組的開始一直排序到數組的結尾。

數組類型:int[]、long[]、short[]、char[]、float[]、double[],還有比較特殊的 byte[]

1. 插入排序(insertion sort)

適合長度短的數組排序,對于byte[] 長度小于等于30 和 其它數組長度小于47 的情況,會使用這種排序

代碼以 int[] a 為例:

// 第一次循環i=j=0,之后每次循環j=i.// j = ++i相當于在每次循環的最后執行 {i++; j = i;}// j = i++相當于在每次循環的最后執行 {j = i; i++;}for (int i = 0, j = i; i < (length - 1); j = ++i) { int ai = a[i + 1]; // 每次循環的目的是將下一個數排到它應該在的位置,這里ai就是下一個數 while (ai < a[j]) { // while循環的目的是確定j的值 和 把所有比ai大的項向后移一位來騰出ai的位置a[j + 1] = a[j]; // 把比ai大的項向后移一位if (j-- == left) { // j-- 確定j的值,也就是確定ai的位置, j 可能等于 -1 break;} } a[j + 1] = ai; // j+1 就是ai的位置}2. 計數排序(counting sort)

只針對byte[] 長度大于30的情況,因為byte的范圍是[-128, 127],只有256個數,所以循環會利用這點

int[] count = new int[256];// 第一次循環:計數for (int i = (0 - 1); ++i <= (length - 1); count[a[i] - (-128)]++);// 第二次循環:給 < byte[] a > 賦值// 循環結束條件以k為標準,k<=0就會停止;// 因為i和k沒有固定關系,所以沒有增量表達式,但在方法體中利用--i和--k進行增量。for (int i = 256, k = length; k > 0; ) { while (count[--i] == 0); // 如果計數個數為0,什么也不做,--i byte value = (byte) (i + (-128)); int s = count[i]; do {a[--k] = value; } while (--s > 0);}3. 快速排序(Quicksort)

適合長度短的數組排序,插入排序也是快速排序的一種。對于byte[] 長度大于30的情況會使用 計數排序,不是這種排序。而對于其它數組長度大于等于47并且小于286 的情況,會使用這種排序。

3.1 對數組做近似7等分

// 7等分一段的長度近似值int seventh = (length >> 3) + (length >> 6) + 1;// 一個數組分為7段,則有五個切割點,如下為五個切割點的下標int e3 = (left + right) >>> 1; // The midpointint e2 = e3 - seventh;int e1 = e2 - seventh;int e4 = e3 + seventh;int e5 = e4 + seventh;3.2 對五個切割點進行插入排序

// Sort these elements using insertion sortif (a[e2] < a[e1]) { int t = a[e2]; a[e2] = a[e1]; a[e1] = t; }if (a[e3] < a[e2]) { int t = a[e3]; a[e3] = a[e2]; a[e2] = t; if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }}if (a[e4] < a[e3]) { int t = a[e4]; a[e4] = a[e3]; a[e3] = t; if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t;if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } }}if (a[e5] < a[e4]) { int t = a[e5]; a[e5] = a[e4]; a[e4] = t; if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t;if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; }} }}3.3 創建兩個變量作為下標記錄值

// 中心部分第一個元素的索引int less = left;// 右部分第一個元素前的索引int great = right;3.4 五個切割點的值都不相同的情況

這種情況會將排序分三塊,變量 pivot1 和 pivot2 作為三塊區域值的區分:第一塊區域所有的值都 < pivot1第二塊區域所有的值都 >= pivot1 并且 <= pivot2第三塊區域所有的值都 > pivot2

3.4.1 第一塊和第三塊處理

// 取兩個值作為分區值int pivot1 = a[e2];int pivot2 = a[e4];// 要排序的第一個和最后一個元素被移動到以前由樞軸占據的位置。// 當分區完成時,軸心點被交換回它們的最終位置,并從隨后的排序中排除。a[e2] = a[left];a[e4] = a[right];// less一開始等于left, great一開始等于right。// 跳過小于或大于分割值的元素。while (a[++less] < pivot1); // 沒有判斷第一個while (a[--great] > pivot2); // 沒有判斷最后一個// 循環帶outer:,`break outer;`會跳出整個循環,也就是結束整個下面的for循環。// less不參與循環,只是一開始給k賦值,less的變化始終是`++less`,用來交換數組中的值。outer:for (int k = less - 1; ++k <= great; ) { int ak = a[k]; if (ak < pivot1) { // Move a[k] to left parta[k] = a[less];/* * Here and below we use 'a[i] = b; i++;' instead * of 'a[i++] = b;' due to performance issue. */a[less] = ak;++less; } else if (ak > pivot2) { // Move a[k] to right partwhile (a[great] > pivot2) { if (great-- == k) {break outer; }}if (a[great] < pivot1) { // a[great] <= pivot2 a[k] = a[less]; a[less] = a[great]; ++less;} else { // pivot1 <= a[great] <= pivot2 a[k] = a[great];}/* * Here and below we use 'a[i] = b; i--;' instead * of 'a[i--] = b;' due to performance issue. */a[great] = ak;--great; }}// 循環結束,交換left和(less - 1)的值,也就是處理循環前`a[e2] = a[left];`導致的分區錯誤a[left] = a[less - 1]; a[less - 1] = pivot1;// 循環結束,交換right和(great + 1)的值,也就是處理循環前`a[e4] = a[right];`導致的分區錯誤a[right] = a[great + 1]; a[great + 1] = pivot2;// 分為三部分后,嵌套排序第一部分和第三部分sort(a, left, less - 2, leftmost);sort(a, great + 2, right, false);3.4.2 第二塊處理

分兩種情況:如果第二塊剩余項超過數組要排序總長度的4/7,會將等于pivot1和等于pivot2的值取出來,再次縮減less和great中間的部分,然后進行排序。否則直接排序。

if (less < e1 && e5 < great) { // 剩余的中間部分超過4/7 /* * Skip elements, which are equal to pivot values. */ while (a[less] == pivot1) {++less; } while (a[great] == pivot2) {--great; } outer: for (int k = less - 1; ++k <= great; ) {int ak = a[k];if (ak == pivot1) { // Move a[k] to left part a[k] = a[less]; a[less] = ak; ++less;} else if (ak == pivot2) { // Move a[k] to right part while (a[great] == pivot2) {if (great-- == k) { break outer;} } if (a[great] == pivot1) { // a[great] < pivot2a[k] = a[less];a[less] = pivot1;++less; } else { // pivot1 < a[great] < pivot2a[k] = a[great]; } a[great] = ak; --great;} }}// Sort center part recursivelysort(a, less, great, false);3.5 五個切割點的值有相同的情況(單軸分區 Partitioning with one pivot)

這種情況也可以理解為將排序分三塊,但只需要一個變量 pivot 作為三塊區域值的區分:第一塊區域所有的值都 < pivot第二塊區域所有的值都 = pivot,因為這塊區域的值都相等,最后就可以不用排序第三塊區域所有的值都 > pivot

// 取下標在中間的值做一個臨時變量,該變量是中值的廉價近似值,作為分割值int pivot = a[e3];// less一開始等于left, great一開始等于right。// 方法體內部不斷修改great的值,使循環執行的次數不斷的縮減,一次循環great可以減少0,可以減少1,可以減少n。// less并不影響循環,只是作為臨時變量進行數組中值的交換,始終小于等于k,一次循環只能加1或不加。for (int k = less; k <= great; ++k) { if (a[k] == pivot) { // 如果a[k]的值等于分割值,跳過continue; } int ak = a[k]; // 取出a[k]值賦給臨時變量ak if (ak < pivot) { // Move a[k] to left parta[k] = a[less];a[less] = ak;++less; } else { // a[k] > pivot - Move a[k] to right partwhile (a[great] > pivot) { --great;}if (a[great] < pivot) { // a[great] <= pivot a[k] = a[less]; a[less] = a[great]; ++less;} else { // a[great] == pivot /* * Even though a[great] equals to pivot, the * assignment a[k] = pivot may be incorrect, * if a[great] and pivot are floating-point * zeros of different signs. Therefore in float * and double sorting methods we have to use * more accurate assignment a[k] = a[great]. */ a[k] = pivot;}a[great] = ak;--great; }}// 分為三部分后,嵌套排序第一部分和第三部分sort(a, left, less - 1, leftmost);sort(a, great + 1, right, false);4. 合并排序(merge sort)

長度很長的數組排序,對于其它數組長度大于等于286 的情況,會使用這種排序。

兩個關鍵常量,起控制作用

// 合并排序中的最大運行次數static final int MAX_RUN_COUNT = 67;// 合并排序中運行的最大長度static final int MAX_RUN_LENGTH = 33;

排序方法

/** * 長度大于等于286的int數組排序 * * @param a * 要排序int數組 * @param left * 起始下標 * @param right * 結束下標 * @param work * null * @param workBase * 0 * @param workLen * 0 */private static void largeSort(int[] a, int left, int right, int[] work,int workBase, int workLen) { /* * Index run[i] is the start of i-th run (ascending or descending * sequence). */ int[] run = new int[MAX_RUN_COUNT + 1]; int count = 0; run[0] = left; // Check if the array is nearly sorted for (int k = left; k < right; run[count] = k) {if (a[k] < a[k + 1]) { // ascending while (++k <= right && a[k - 1] <= a[k]);} else if (a[k] > a[k + 1]) { // descending while (++k <= right && a[k - 1] >= a[k]); for (int lo = run[count] - 1, hi = k; ++lo < --hi;) {int t = a[lo];a[lo] = a[hi];a[hi] = t; }} else { // equal for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k];) {if (--m == 0) { sort(a, left, right, true); return;} }}/* * The array is not highly structured, use Quicksort instead of * merge sort. */if (++count == MAX_RUN_COUNT) { sort(a, left, right, true); return;} } // Check special cases // Implementation note: variable 'right' is increased by 1. if (run[count] == right++) { // The last run contains one elementrun[++count] = right; } else if (count == 1) { // The array is already sortedreturn; } // Determine alternation base for merge byte odd = 0; for (int n = 1; (n <<= 1) < count; odd ^= 1); // Use or create temporary array b for merging int[] b; // temp array; alternates with a int ao, bo; // array offsets from ’left’ int blen = right - left; // space needed for b if (work == null || workLen < blen || workBase + blen > work.length) {work = new int[blen];workBase = 0; } if (odd == 0) {System.arraycopy(a, left, work, workBase, blen);b = a;bo = 0;a = work;ao = workBase - left; } else {b = work;ao = 0;bo = workBase - left; } // Merging for (int last; count > 1; count = last) {for (int k = (last = 0) + 2; k <= count; k += 2) { int hi = run[k], mi = run[k - 1]; for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {b[i + bo] = a[p++ + ao];} else { b[i + bo] = a[q++ + ao];}}run[++last] = hi;}if ((count & 1) != 0) {for (int i = right, lo = run[count - 1]; --i >= lo; b[i + bo] = a[i + ao]);run[++last] = right;}int[] t = a;a = b;b = t;int o = ao;ao = bo;bo = o;}}

以上就是Java使用DualPivotQuicksort排序的詳細內容,更多關于DualPivotQuicksort排序的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 亚洲国产成人最新精品资源 | 99成人在线视频 | 国产原创在线视频 | 欧美一级精品 | 老外一级毛片免费看 | 成人一区视频 | 在线免费观看国产视频 | 欧美成人精品动漫在线专区 | 在线免费精品视频 | 日韩美一区二区 | 成年人网站免费 | 一级毛片看一个 | 欧美色视频日本片高清在线观看 | 欧美一区二区三区精品影视 | 免费一级在线 | 亚洲天堂一区二区 | 一级特黄欧美 | 免费视频 久久久 | 天天看夜夜看 | 2020国产精品 | 萌白酱喷水福利视频在线 | 特毛片| 亚洲成av人片在线观看无码 | 97久草| 521av香蕉 | 亚洲欧美在线精品一区二区 | 亚洲国产系列久久精品99人人 | 国产伦一区二区三区四区久久 | 亚洲b| 欧美成人aaa大片 | 国产精品永久免费视频观看 | 最近最新中文字幕免费的一页 | 欧美成人专区 | 久久精品午夜视频 | 美女网站18| 国产一区二区福利久久 | 欧美激情性色生活片在线观看 | shkd在线观看 | 操哭美女| 99国产福利视频区 | 天天视频一区二区三区 |