常用排序算法有:
1、选择排序(直接选择排序、堆排序)
2、交换排序(冒泡排序、快速排序)
3、插入排序(直接插入排序、二分插入排序、Shell排序)
4、归并排序
5、桶式排序
6、基数排序
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1、直接选择排序
(1)、首先将第一个与第二个进行比较,如果第二个比第一个小,交换二者的位置,然后第二个与第三个进行比较…………第一趟找出最小的数据放在第一位置
(2)、第二趟从第二个开始,找出第二小的数据放在第二的位置
………………
经过N-1次排序之后就实现从小到大的排序,核心代码就是一个双重循环
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); Sort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void Sort(int[] arrays) { int temp; for (int i = 0; i < arrays.length - 1; i++) { for (int j = i + 1; j < arrays.length; j++) { if (arrays[i] > arrays[j]) { temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } } } } run: 排序前:[67, 62, 79, 29, 1, 46, 66, 50, 34, 93] 排序后:[1, 29, 34, 46, 50, 62, 66, 67, 79, 93] 成功构建 (总时间: 0 秒)
在排序中发现一个问题,由于每一次外部循环,只需要寻找最小的那个数据,然后放到开始位置去,
然后程序只要已发现前面数据比后面大,马上就会交换它们的未知,这里就增加了其开销
下面改进一下,在内部循环的时候,寻找当次外循环的最小值的位置,把这个位置记录下来,与它进行比较,然后再来交换
private static void Sort(int[] arrays) { int temp; int index; for (int i = 0; i < arrays.length - 1; i++) { index = i; for (int j = i + 1; j < arrays.length; j++) { if (arrays[index] > arrays[j]) { index = j; } } if (index != i) { temp = arrays[i]; arrays[i] = arrays[index]; arrays[index] = temp; } } }
对于直接选择排序假设有N项数据,数据交换次数最多有N-1次,程序比较次数较多,时间效率为O(N*N);但是其空间利用率高,只需要一个额外变量用于交换,空间效率O(1);直接选择排序是不稳定的。
2、堆排序
针对N个数据为:K0,K1,K2………………Kn,如果满足以下关系
Ki<=k2i+1 并且Ki<=K2i+2 (i=0,1,2…………)
则称其为小顶堆(小根堆)
反之:
Ki>=k2i+1 并且Ki>=K2i+2 (i=0,1,2…………)
则称其为大顶堆(大根堆)
步骤:
1、第一趟将索引0——N-1的数据建立大顶堆(小顶堆),就可以选出最大(最小)的数据放到根节点(索引0位置),然后将未知0与N-1位置的数据兑换,
那么最大(最小)的数据就跑到最后去了
2、第二趟将索引0——N-2的数据建立大顶堆(小顶堆),就可以选出最大(最小)的数据放到根节点(索引0位置),然后将未知0与N-2位置的数据兑换,
那么最大(最小)的数据就跑到倒数第二的位置去了
……………………以此类推就实现排序了
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); heapSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } public static void heapSort(int[] arrays) { for (int i = 0; i < arrays.length - 1; i++) { buildMaxHeap(arrays, arrays.length - 1 - i); swap(arrays, 0, arrays.length - 1 - i); } } private static void buildMaxHeap(int[] arrays, int lastIndex) { for (int i = (lastIndex - 1) / 2; i >= 0; i--) { int k = i; while (2 * k + 1 <= lastIndex) {//当前k节点存在子节点 int biggerIndex = 2 * k + 1;//左节点 if (biggerIndex < lastIndex) {//左节点索引小于最大索引未知、说明存在右节点且右节点索引等于lastIndex if (arrays[biggerIndex] < arrays[biggerIndex + 1]) { biggerIndex++; } } if (arrays[k] < arrays[biggerIndex]) { swap(arrays, k, biggerIndex); k = biggerIndex; } else { break; } }//end while }//end for } private static void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } run: 排序前:[77, 69, 10, 97, 61, 56, 35, 44, 89, 81] 排序后:[10, 35, 44, 56, 61, 69, 77, 81, 89, 97] 成功构建 (总时间: 0 秒)
假设有N项数据,那么就要进行N-1次建堆,每次建堆耗时log2n,起时间效率为O(nlog2n);但是其空间效率很高,为O(1);堆排序是不稳定的
3、冒泡排序
冒泡排序时候,数据要不断的进行交换,属于交换排序
第一趟:比较0与1、1月2…………n-2与n-1,只要第一个数对第二个数大,就交换位置,那么最后一个就是最大的
第二趟:比较0与1、1月2…………n-3与n-2,只要第一个数对第二个数大,就交换位置,那么最后一个就是倒数第二大的
………………以此类推
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); bubbleSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void bubbleSort(int[] arrays) { for (int i = 0; i < arrays.length - 1; i++) { boolean flag = false; for (int j = 0; j < arrays.length - 1 - i; j++) { if (arrays[j] > arrays[j + 1]) { swap(arrays, j, j + 1); flag = true; }//end if }//end for inner if (!flag) {//某一趟没有发生交换说明已经排好序了 break; } }//end for outer } private static void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } run: 排序前:[66, 8, 74, 61, 6, 99, 60, 73, 64, 53] 排序后:[6, 8, 53, 60, 61, 64, 66, 73, 74, 99] 成功构建 (总时间: 0 秒)
冒泡排序最坏情况下:需要做n*(n-1)/2比较;移动次数n*(n-1)*3/2;空间利用率O(1);
冒泡排序是稳定的
4、快速排序
快速排序是一种速度非常快的交换排序方法。
思路:从待排序数据中任取一个数据(第一个)做为分界值,所有比它小的放到左边,大的放到右边;
这样第一趟就形成了两个自序列,然后分别对这两个自序列递归进行,直到每一个子序列只有一个元素就可以了
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); quickSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void quickSort(int[] arrays) { subSort(arrays, 0, arrays.length - 1); } private static void subSort(int[] arrays, int start, int end) { if (start < end) { int base = arrays[start];//首元素做为分界值 int left = start + 1; int right = end; while (1 == 1) { while (left < end && arrays[left] <= base) {//从左到右找到大于base的 left++; } while (right > start && arrays[right] >= base) {//从右到左找到小于base的 right--; } if (left < right) { swap(arrays, left, right); } else { break; } }//end while swap(arrays, start, right); subSort(arrays, start, right - 1);//递归左边 subSort(arrays, right + 1, end);//递归右边 }//end if } private static void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } run: 排序前:[80, 87, 32, 30, 75, 35, 60, 17, 74, 59] 排序后:[17, 30, 32, 35, 59, 60, 74, 75, 80, 87] 成功构建 (总时间: 0 秒)
快速排序是不稳定的,空间利用率O(log2n) ,时间效率很高
5、直接插入排序
思路:依次将需要排序的数据按其关键字的大小插入前面的有序序列
对于一个有N个元素的序列;
1、第一趟,将第二个元素插入前面序列,目前前面那个序列只有一个元素
2、第二趟,将第三个元素插入前面序列,前面有两个数据,
…………N-1次之后就实现了排序
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); insertSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void insertSort(int[] arrays) { for (int i = 1; i < arrays.length; i++) { int temp = arrays[i]; if (arrays[i] < arrays[i - 1]) { int j = i - 1; //先整体后移一步然后再插入 for (; j >= 0 && arrays[j] > temp; j--) { arrays[j + 1] = arrays[j]; }//end for inner arrays[j + 1] = temp; } }//end for outer } private static void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } run: 排序前:[71, 60, 29, 5, 57, 88, 89, 62, 37, 96] 排序后:[5, 29, 37, 57, 60, 62, 71, 88, 89, 96] 成功构建 (总时间: 0 秒)
直接插入时间效率并不高,为O(n*n),但是控件利用率高,为O(1),直接插入排序是稳定的。
6、二分插入排序
1、计算0—i-1索引的中间点,用i处的元素与(0+i-1)/2出的元素进行比较,如果i出的元素大,则在(0+i-1)/2—i-1范围内搜索;反之在0—(0+i-1)/2范围内搜索
2、按照步骤1不断的进行此操作,范围缩小到1/2,1/4,1/8,从而决定出第i个元素的插入位置
3、一旦确认出i个元素的插入位置,下面只需要将元素整体后移一步,然后将i个元素放进去
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); binaryInsertSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void binaryInsertSort(int[] arrays) { for (int i = 1; i < arrays.length; i++) { int temp = arrays[i]; int left = 0; int right = i - 1; while (left <= right) { int middle = (left + right) / 2; if (temp > arrays[middle]) { left = middle + 1; } else { right = middle - 1; } }//end while for (int j = i; j > left; j--) { arrays[j] = arrays[j - 1]; }//end for inner arrays[left] = temp; }//end for } private static void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } run: 排序前:[81, 63, 51, 73, 55, 46, 23, 12, 18, 73] 排序后:[12, 18, 23, 46, 51, 55, 63, 73, 73, 81] 成功构建 (总时间: 0 秒)
二分插入排序与直接插入排序效果差不多,只是速度更快
7、Shell排序
Shell排序对直接插入排序进行了改进:通过加大排序中元素之间的间隔,并在这些有间隔的元素之间插入排序,从而使数据项大跨度移动。当这些数据经过一次排序之后,Shell排序算法减小数据项的间隔在排序,依次进行下去,这些间隔被成为增量。
h=h*3+1
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); shellSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void shellSort(int[] arrays) { int arrayLength = arrays.length; int h = 1; while (h < arrayLength / 3) { h = h * 3 + 1; } while (h > 0) { for (int i = h; i < arrayLength; i++) { int temp = arrays[i]; if (arrays[i] < arrays[i - h]) { int j = i - h; //整体后移一位 for (; j >= 0 && arrays[j] > temp; j -= h) { arrays[j + h] = arrays[j]; }//end for inner arrays[j + h] = temp; } }//end for outer h = (h - 1) / 3; }//end while } private static void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } } run: 排序前:[36, 82, 11, 7, 5, 26, 48, 37, 11, 62] 排序后:[5, 7, 11, 11, 26, 36, 37, 48, 62, 82] 成功构建 (总时间: 0 秒)
Shell排序是直接插入排序的改进型,因此是稳定的,速度更快
8、归并排序
归并排序是将两个有序的序列合并在一起组成一个新的序列。
首先将排序序列堪称N个长度为1的序列,首先做两个两个的合并,得到N/2个长度为2的有序序列,如此循环………………最终得到一个长度为N的序列。
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); mergeSort(arrays); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void mergeSort(int[] arrays) { sort(arrays, 0, arrays.length - 1); } private static void sort(int[] arrays, int left, int right) { if (left < right) { //求中间位置 int center = (left + right) / 2; //对左边数组排序 sort(arrays, left, center); //对右边数组排序 sort(arrays, center + 1, right); //合并 merge(arrays, left, center, right); } } private static void merge(int[] arrays, int left, int center, int right) { int[] tempArray = new int[arrays.length]; int middle = center + 1; int tmpIndex = left; int cpIndex = left; while (left <= center && middle <= right) { //选出两个数组中最小的那个放到中间数组 if (arrays[middle] >= arrays[left]) { tempArray[tmpIndex++] = arrays[left++]; } else { tempArray[tmpIndex++] = arrays[middle++]; } }//end while //剩余数据依次放入中间数组 while (middle <= right) { tempArray[tmpIndex++] = arrays[middle++]; } while (left <= center) { tempArray[tmpIndex++] = arrays[left++]; } //将中间数组的数据复制到原数组 while (cpIndex <= right) { arrays[cpIndex] = tempArray[cpIndex++]; } } } run: 排序前:[41, 98, 45, 20, 90, 56, 64, 80, 27, 13] 排序后:[13, 20, 27, 41, 45, 56, 64, 80, 90, 98] 成功构建 (总时间: 0 秒)
归并排序的空间效率很差,因为需要一个中间数组,时间复杂度为O(nlog2n);归并排序是稳定的。
9、桶式排序
桶式排序不再是基于比较的排序,其需要满足以下几个条件:
(1)、待排数据的所有值处于一个可以枚举的范围之内
(2)、这个枚举范围不应该很大,否则开销很大
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); bucketSort(arrays, 1, 100); System.out.println("排序后:" + Arrays.toString(arrays)); } private static void bucketSort(int[] arrays, int min, int max) { int[] tempArray = new int[arrays.length]; int[] buckets = new int[max - min]; //计算每个元素在序列中出现的次数 for (int i = 0; i < arrays.length; i++) { buckets[arrays[i] - min]++; } //计算桶内各元素在有序序列中的位置 for (int i = 1; i < max - min; i++) { buckets[i] = buckets[i] + buckets[i - 1]; } //将待排数据全部复制到中间数组里面 System.arraycopy(arrays, 0, tempArray, 0, arrays.length); //根据buckets数组的信息将待排列的数据放入对应的位置 for (int k = arrays.length - 1; k >= 0; k--) { arrays[--buckets[tempArray[k] - min]] = tempArray[k]; } } } run: 排序前:[83, 40, 66, 68, 34, 31, 20, 51, 13, 75] 排序后:[13, 20, 31, 34, 40, 51, 66, 68, 75, 83] 成功构建 (总时间: 0 秒)
桶式排序的时间效率很高,但是空间开销太大,因为需要两个中间数组;桶式排序是稳定的。
10、基数排序不是单一的排序算法,需要依赖其他排序算法,而这个排序算法必须是稳定的。基数排序将待排列数据分成多个关键字排序,基数排序的实质是关键字排序。
package example; import java.util.Arrays; import java.util.Random; public class Test { public static void main(String[] args) { Random rd = new Random(); int[] arrays = new int[10]; for (int i = 0; i < arrays.length; i++) { arrays[i] = rd.nextInt(100); } System.out.println("排序前:" + Arrays.toString(arrays)); radixSort(arrays, 10, 2); System.out.println("排序后:" + Arrays.toString(arrays)); } /** * 基数排序ASC(中间使用桶式排序) * * @param arrays 待排数组ASC * @param radix 关键字拆分的进制 10代表十进制 * @param count 将关键字拆分成几个关键字 */ private static void radixSort(int[] arrays, int radix, int count) { int[] tempArray = new int[arrays.length]; int[] buckets = new int[radix]; for (int i = 0, rate = 1; i < count; i++) { Arrays.fill(buckets, 0);//重置数组,开始统计下一个关键字 System.arraycopy(arrays, 0, tempArray, 0, arrays.length);//将待排数据复制到中间数组 for (int j = 0; j < arrays.length; j++) { int key = (tempArray[j] / rate) % radix; buckets[key]++; } for (int j = 1; j < radix; j++) { buckets[j] = buckets[j] + buckets[j - 1]; } //按子关键字对数据进行排序 for (int k = arrays.length - 1; k >= 0; k--) { int key = (tempArray[k] / rate) % radix; arrays[--buckets[key]] = tempArray[k]; } rate *= radix; }//end for outer } } run: 排序前:[98, 39, 38, 2, 84, 39, 87, 88, 35, 79] 排序后:[2, 35, 38, 39, 39, 79, 84, 87, 88, 98] 成功构建 (总时间: 0 秒)
排序法 | 平均时间 | 最差情形 | 稳定度 | 额外空间 | 备注 |
冒泡 | O(n2) | O(n2) | 稳定 | O(1) | n小时较好 |
交换 | O(n2) | O(n2) | 不稳定 | O(1) | n小时较好 |
选择 | O(n2) | O(n2) | 不稳定 | O(1) | n小时较好 |
插入 | O(n2) | O(n2) | 稳定 | O(1) | 大部分已排序时较好 |
基数 | O(logRB) | O(logRB) | 稳定 | O(n) | B是真数(0-9), R是基数(个十百) |
Shell | O(nlogn) | O(ns) 1<s<2 | 不稳定 | O(1) | s是所选分组 |
快速 | O(nlogn) | O(n2) | 不稳定 | O(nlogn) | n大时较好 |
归并 | O(nlogn) | O(nlogn) | 稳定 | O(1) | n大时较好 |
堆 | O(nlogn) | O(nlogn) | 不稳定 | O(1) | n大时较好 |
package sortUtility; import java.util.Arrays; /** * * @author Administrator */ public class SortUtility { //////////////////////////////////选择排序-beign///////////////////////////////////////////// /** * @deprecated 直接选择排序ASC * @param arrays 需要排序的数组 */ public void directSelectSort(int[] arrays) { for (int i = 0; i < arrays.length - 1; i++) { for (int j = i + 1; j < arrays.length; j++) { if (arrays[i] > arrays[j]) { swap(arrays, i, j); }//end if }//end for inner }//end for outer } /** * @deprecated 优化的直接选择排序ASC(减少数据交换次数) * @param arrays 需要排序的数组 */ public void directSelectSortNew(int[] arrays) { int index; for (int i = 0; i < arrays.length - 1; i++) { index = i; for (int j = i + 1; j < arrays.length; j++) { if (arrays[index] > arrays[j]) { index = j; } } if (index != i) { swap(arrays, i, index); } } } public void heapSort(int[] arrays) { for (int i = 0; i < arrays.length - 1; i++) { buildMaxHeap(arrays, arrays.length - 1 - i); swap(arrays, 0, arrays.length - 1 - i); } } /** * @deprecated 建立大顶堆(根节点>=左子节点 AND 根节点>=右子节点) * @param arrays 需排序数组 * @param lastIndex 最后一个节点 */ private void buildMaxHeap(int[] arrays, int lastIndex) { for (int i = (lastIndex - 1) / 2; i >= 0; i--) { int k = i; while (2 * k + 1 <= lastIndex) {//当前k节点存在子节点 int biggerIndex = 2 * k + 1;//左节点 if (biggerIndex < lastIndex) {//左节点索引小于最大索引未知、说明存在右节点且右节点索引等于最大索引 if (arrays[biggerIndex] < arrays[biggerIndex + 1]) { biggerIndex++; } } if (arrays[k] < arrays[biggerIndex]) { swap(arrays, k, biggerIndex); k = biggerIndex; } else { break; } }//end while }//end for } //////////////////////////////////选择排序-end///////////////////////////////////////////// //////////////////////////////////交换排序-begin///////////////////////////////////////////// /** * @deprecated 冒泡排序ASC * @param arrays 需排序数组 */ public void bubbleSort(int[] arrays) { for (int i = 0; i < arrays.length - 1; i++) { boolean flag = false; for (int j = 0; j < arrays.length - 1 - i; j++) { if (arrays[j] > arrays[j + 1]) { swap(arrays, j, j + 1); flag = true; }//end if }//end for inner if (!flag) {//某一趟没有发生交换说明已经排好序了 break; } }//end for outer } /** * @deprecated 快速排序ASC * @param arrays 需排序数组 */ public void quickSort(int[] arrays) { subSort(arrays, 0, arrays.length - 1); } private void subSort(int[] arrays, int start, int end) { if (start < end) { int base = arrays[start];//首元素做为分界值 int left = start + 1; int right = end; while (1 == 1) { while (left < end && arrays[left] <= base) {//从左到右找到大于base的 left++; } while (right > start && arrays[right] >= base) {//从右到左找到小于base的 right--; } if (left < right) { swap(arrays, left, right); } else { break; } }//end while swap(arrays, start, right); subSort(arrays, start, right - 1);//递归左边 subSort(arrays, right + 1, end);//递归右边 }//end if } //////////////////////////////////交换排序-end///////////////////////////////////////////// //////////////////////////////////插入排序-begin///////////////////////////////////////////// /** * @deprecated 直接插入排序ASC * @param arrays 需排序数组 */ public void insertSort(int[] arrays) { for (int i = 1; i < arrays.length; i++) { int temp = arrays[i]; if (arrays[i] < arrays[i - 1]) { int j = i - 1; //先整体后移一步然后再插入 for (; j >= 0 && arrays[j] > temp; j--) { arrays[j + 1] = arrays[j]; }//end for inner arrays[j + 1] = temp; } }//end for outer } /** * @deprecated 二分插入排序ASC * @param arrays 需排序数组 */ public void binaryInsertSort(int[] arrays) { for (int i = 1; i < arrays.length; i++) { int temp = arrays[i]; int left = 0; int right = i - 1; while (left <= right) { int middle = (left + right) / 2; if (temp > arrays[middle]) { left = middle + 1; } else { right = middle - 1; } }//end while for (int j = i; j > left; j--) { arrays[j] = arrays[j - 1]; }//end for inner arrays[left] = temp; }//end for } /** * @deprecated Shell排序ASC * @param arrays 需排序数组 */ public void shellSort(int[] arrays) { int arrayLength = arrays.length; int h = 1; while (h < arrayLength / 3) { h = h * 3 + 1; } while (h > 0) { for (int i = h; i < arrayLength; i++) { int temp = arrays[i]; if (arrays[i] < arrays[i - h]) { int j = i - h; //整体后移一位 for (; j >= 0 && arrays[j] > temp; j -= h) { arrays[j + h] = arrays[j]; }//end for inner arrays[j + h] = temp; } }//end for outer h = (h - 1) / 3; }//end while } //////////////////////////////////插入排序-end///////////////////////////////////////////// //////////////////////////////////归并排序-begin/////////////////////////////////////////// /** * @deprecated 归并排序ASC * @param arrays 待排数组 */ public void mergeSort(int[] arrays) { sort(arrays, 0, arrays.length - 1); } /** * @deprecated 递归排序 * @param arrays 待排数组 * @param left 数组第一个元素索引 * @param right 数组最后一个元素索引 */ private void sort(int[] arrays, int left, int right) { if (left < right) { //求中间位置 int center = (left + right) / 2; //对左边数组排序 sort(arrays, left, center); //对右边数组排序 sort(arrays, center + 1, right); //合并 merge(arrays, left, center, right); } } /** * @deprecated 将两个数组归并 * @param arrays 待排数组 * @param left 左数组第一个元素索引 * @param center 左数组最后一个元素 center+1为右数组第一个元素索引 * @param right 右数组最后一个元素索引 */ private void merge(int[] arrays, int left, int center, int right) { int[] tempArray = new int[arrays.length]; int middle = center + 1; int tmpIndex = left; int cpIndex = left; while (left <= center && middle <= right) { //选出两个数组中最小的那个放到中间数组 if (arrays[middle] >= arrays[left]) { tempArray[tmpIndex++] = arrays[left++]; } else { tempArray[tmpIndex++] = arrays[middle++]; } }//end while //剩余数据依次放入中间数组 while (middle <= right) { tempArray[tmpIndex++] = arrays[middle++]; } while (left <= center) { tempArray[tmpIndex++] = arrays[left++]; } //将中间数组的数据复制到原数组 while (cpIndex <= right) { arrays[cpIndex] = tempArray[cpIndex++]; } } //////////////////////////////////归并排序-end///////////////////////////////////////////// //////////////////////////////////桶式排序-begin/////////////////////////////////////////// /** * @deprecated 桶式排序ASC * @param min 枚举范围最小值 * @param max 枚举范围最大值 */ public void bucketSort(int[] arrays, int min, int max) { int[] tempArray = new int[arrays.length]; int[] buckets = new int[max - min]; //计算每个元素在序列中出现的次数 for (int i = 0; i < arrays.length; i++) { buckets[arrays[i] - min]++; } //计算桶内各元素在有序序列中的位置 for (int i = 1; i < max - min; i++) { buckets[i] = buckets[i] + buckets[i - 1]; } //将待排数据全部复制到中间数组里面 System.arraycopy(arrays, 0, tempArray, 0, arrays.length); //根据buckets数组的信息将待排列的数据放入对应的位置 for (int k = arrays.length - 1; k >= 0; k--) { arrays[--buckets[tempArray[k] - min]] = tempArray[k]; } } //////////////////////////////////桶式排序-end///////////////////////////////////////////// //////////////////////////////////基数排序-begin/////////////////////////////////////////// /** * 基数排序ASC(中间使用桶式排序) * * @param arrays 待排数组ASC * @param radix 关键字拆分的进制 10代表十进制 * @param count 将关键字拆分成几个关键字 */ public void radixSort(int[] arrays, int radix, int count) { int[] tempArray = new int[arrays.length]; int[] buckets = new int[radix]; for (int i = 0, rate = 1; i < count; i++) { Arrays.fill(buckets, 0);//重置数组,开始统计下一个关键字 System.arraycopy(arrays, 0, tempArray, 0, arrays.length);//将待排数据复制到中间数组 for (int j = 0; j < arrays.length; j++) { int key = (tempArray[j] / rate) % radix; buckets[key]++; } for (int j = 1; j < radix; j++) { buckets[j] = buckets[j] + buckets[j - 1]; } //按子关键字对数据进行排序 for (int k = arrays.length - 1; k >= 0; k--) { int key = (tempArray[k] / rate) % radix; arrays[--buckets[key]] = tempArray[k]; } rate *= radix; }//end for outer } //////////////////////////////////基数排序-end///////////////////////////////////////////// /** * @deprecated 交换数据 */ private void swap(int[] arrays, int i, int j) { int temp; temp = arrays[i]; arrays[i] = arrays[j]; arrays[j] = temp; } }