/**
* @author: shihchieh.ma
* @create: 2020/6/15 6:13 下午
* @email: shihchieh.ma@gail.com
* @description:
*/
public class Sort {
public static final int[] INTS = {
// 24, 352, 23, 4, 1, 421, 5, 6, 436, 7, 86, 97, 9, 74, 34, 234, 1, 3, 6, 7
10, 8, 6, 4, 2
};
/**
* @param n 生成n個(gè)元素的隨機(jī)數(shù)組
* @param rangeL 隨機(jī)范圍[rangeL
* @param rangeR rangeR]
* @return 返回一個(gè)隨機(jī) int 型數(shù)組
*/
public static int[] gennerateArray(int n, int rangeL, int rangeR) {
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = (int) (Math.random() * (rangeR - rangeL + 1)) + rangeL;
}
return arr;
}
public static void main(String[] args) {
// int[] INTS = gennerateArray(1000, 10);
long startTime, endTime;
// 冒泡排序
int[] bubbleArr = INTS.clone();
startTime = System.currentTimeMillis();
bubbleSort(bubbleArr);
endTime = System.currentTimeMillis();
printArray("冒泡排序:", bubbleArr, endTime - startTime);
// 選擇排序
int[] selectionArr = INTS.clone();
startTime = System.currentTimeMillis();
selectionSort(selectionArr);
endTime = System.currentTimeMillis();
printArray("選擇排序:", selectionArr, endTime - startTime);
// 插入排序
int[] insertArr = INTS.clone();
startTime = System.currentTimeMillis();
insertSort(insertArr);
endTime = System.currentTimeMillis();
printArray("插入排序:", insertArr, endTime - startTime);
// 快速排序
int[] quickArr = INTS.clone();
startTime = System.currentTimeMillis();
quickSort(quickArr, 0, quickArr.length - 1);
endTime = System.currentTimeMillis();
printArray("快速排序:", quickArr, endTime - startTime);
// 計(jì)數(shù)排序
int[] countArr = INTS.clone();
startTime = System.currentTimeMillis();
int[] countSort = countSort(countArr);
endTime = System.currentTimeMillis();
printArray("計(jì)數(shù)排序:", countSort, endTime - startTime);
// 基數(shù)排序
int[] radixArr = INTS.clone();
startTime = System.currentTimeMillis();
radixSort(radixArr);
endTime = System.currentTimeMillis();
printArray("基數(shù)排序:", radixArr, endTime - startTime);
// 桶排序
int[] bucketArr = INTS.clone();
startTime = System.currentTimeMillis();
int[] bucketSort = bucketSort(bucketArr);
endTime = System.currentTimeMillis();
printArray("桶排序:", bucketSort, endTime - startTime);
// 歸并排序
int[] mergeArr = INTS.clone();
startTime = System.currentTimeMillis();
mergeSort(mergeArr, 0, mergeArr.length - 1, new int[mergeArr.length]);
endTime = System.currentTimeMillis();
printArray("歸并排序:", mergeArr, endTime - startTime);
// 希爾排序
int[] shellArr = INTS.clone();
startTime = System.currentTimeMillis();
shellSort(shellArr);
endTime = System.currentTimeMillis();
printArray("希爾排序:", shellArr, endTime - startTime);
// 堆排序
int[] heapArr = INTS.clone();
startTime = System.currentTimeMillis();
heapSort(heapArr);
endTime = System.currentTimeMillis();
printArray("堆排序:", heapArr, endTime - startTime);
}
private static void printArray(String name, int[] ints, long time) {
for (int anInt : ints) {
System.out.print("_" + anInt + "_");
}
System.out.println("\t");
System.out.println(name + "耗時(shí):" + time);
System.out.println();
}
}
冒泡排序
- 比較相鄰的元素。如果第一個(gè)比第二個(gè)大,就交換他們兩個(gè)。
- 對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對。這步做完后,最后的元素會是最大的數(shù)。
- 針對所有的元素重復(fù)以上的步驟,除了最后一個(gè)。
- 持續(xù)每次對越來越少的元素重復(fù)上面的步驟,直到?jīng)]有任何一對數(shù)字需要比較。

/** 冒泡排序 */
private static void bubbleSort(int[] clone) {
for (int i = 0, j = clone.length; i < j; i++) {
for (int k = 0, l = j - 1 - i; k < l; k++) {
if (clone[k] > clone[k + 1]) {
clone[k] = clone[k] ^ clone[k + 1];
clone[k + 1] = clone[k] ^ clone[k + 1];
clone[k] = clone[k] ^ clone[k + 1];
}
}
}
}
選擇排序
- 在未排序序列中找到最?。ù螅┰兀娣诺脚判蛐蛄械钠鹗嘉恢?/li>
- 從剩余未排序元素中繼續(xù)尋找最?。ù螅┰兀缓蠓诺揭雅判蛐蛄械哪┪?/li>
- 以此類推,直到所有元素均排序完畢

/** 選擇排序 */
private static void selectionSort(int[] clone) {
for (int i = 0, j = clone.length; i < j; i++) {
int minIndex = i;
for (int k = i; k < j; k++) {
if (clone[k] < clone[minIndex]) {
minIndex = k;
}
}
if (minIndex != i) {
clone[i] = clone[i] + clone[minIndex];
clone[minIndex] = clone[i] - clone[minIndex];
clone[i] = clone[i] - clone[minIndex];
}
}
}
插入排序
- 第一個(gè)元素開始,該元素可以認(rèn)為已經(jīng)被排序
- 取出下一個(gè)元素,在已經(jīng)排序的元素序列中從后向前掃描
- 如果該元素(已排序)大于新元素,將該元素移到下一位置
- 重復(fù)步驟3,直到找到已排序的元素小于或者等于新元素的位置
- 將新元素插入到該位置后
- 重復(fù)步驟 2->5

/** 插入排序 */
private static void insertSort(int[] clone) {
for (int i = 1, j = clone.length; i < j; i++) {
int k = i;
int temp = clone[k];
while (k > 0 && clone[k - 1] > temp) {
clone[k] = clone[k - 1];
k--;
}
clone[k] = temp;
}
}
快速排序
- 選取第一個(gè)數(shù)為基準(zhǔn)
- 將比基準(zhǔn)小的數(shù)交換到前面,比基準(zhǔn)大的數(shù)交換到后面
- 對左右區(qū)間重復(fù)第二步,直到各區(qū)間只有一個(gè)數(shù)

/**
* 快速排序
*
* @param clone 數(shù)組
* @param leftIndex 左邊角標(biāo) 初始0
* @param rightIndex 右邊角標(biāo) 初始length-1
*/
private static void quickSort(int[] clone, int leftIndex, int rightIndex) {
// temp-基準(zhǔn)位
int i, j, temp;
if (leftIndex > rightIndex) {
return;
}
i = leftIndex;
j = rightIndex;
temp = clone[leftIndex];
while (i < j) {
// 先右邊,往左遞減,找一個(gè)小于基準(zhǔn)位的數(shù)
// 當(dāng)右邊的角標(biāo)位置所在的數(shù)>基準(zhǔn)位的數(shù)時(shí),繼續(xù)從右往左找(同時(shí) j 索引-1)
// 找到就跳出 while循環(huán)
while (temp <= clone[j] && i < j) {
j--;
}
// 再左邊,往右遞增
// 如上
while (temp >= clone[i] && i < j) {
i++;
}
// 滿足條件則交換
if (i < j) {
clone[i] = clone[i] + clone[j];
clone[j] = clone[i] - clone[j];
clone[i] = clone[i] - clone[j];
}
}
// i=j 左右在同一位置
// 最后將基準(zhǔn)為與i和j相等位置的數(shù)字交換
clone[leftIndex] = clone[i];
clone[i] = temp;
// 左半數(shù)組<(i或j所在索引的數(shù))<右半數(shù)組
// 也就是說(i或j所在索引的數(shù))已經(jīng)確定排序位置,就不用再排序了,
// 相同的方法分別處理左右數(shù)組
// 遞歸調(diào)用左半數(shù)組
quickSort(clone, leftIndex, j - 1);
// 遞歸調(diào)用右半數(shù)組
quickSort(clone, j + 1, rightIndex);
}
計(jì)數(shù)排序

- 找出待排序的數(shù)組中最大和最小的元素;
- 統(tǒng)計(jì)數(shù)組中每個(gè)值為 i 的元素出現(xiàn)的次數(shù),存入數(shù)組 C 的第 i 項(xiàng);
- 對所有的計(jì)數(shù)累加(從 C 中的第一個(gè)元素開始,每一項(xiàng)和前一項(xiàng)相加);
- 向填充目標(biāo)數(shù)組:將每個(gè)元素 i 放在新數(shù)組的第 C[i] 項(xiàng),每放一個(gè)元素就將 C[i] 減去 1;
當(dāng)數(shù)組最大和最小差值過大時(shí),不適合計(jì)數(shù)排序
當(dāng)數(shù)組元素不是整數(shù)時(shí),不適合用計(jì)數(shù)排序
/** 計(jì)數(shù)排序 */
private static int[] countSort(int[] clone) {
int max = clone[0];
int min = clone[0];
for (int i = 1, j = clone.length; i < j; i++) {
if (clone[i] > max) {
max = clone[i];
}
if (clone[i] < min) {
min = clone[i];
}
}
int dValue = max - min;
int[] countArray = new int[dValue + 1];
for (int value : clone) {
countArray[value - min]++;
}
// 統(tǒng)計(jì)數(shù)組做變形,后邊的元素等于前面的元素之和
for (int i = 1; i < countArray.length; i++) {
countArray[i] += countArray[i - 1];
}
// 倒序遍歷原始數(shù)組,從統(tǒng)計(jì)數(shù)組中找到正確的位置,輸出到結(jié)果數(shù)組
int[] sortedArray = new int[clone.length];
for (int i = clone.length - 1; i >= 0; i--) {
// 給sortedArray的當(dāng)前位置賦值
sortedArray[countArray[clone[i] - min] - 1] = clone[i];
// 給countArray的位置的值--
countArray[clone[i] - min]--;
}
return sortedArray;
}
基數(shù)排序
- 取得數(shù)組中的最大數(shù),并取得位數(shù);
- arr為原始數(shù)組,從最低位開始取每個(gè)位組成radix數(shù)組;
- 對radix進(jìn)行計(jì)數(shù)排序

/** 基數(shù)排序 */
private static void radixSort(int[] clone) {
int maxLength = 0;
// 最大位數(shù)
for (int i : clone) {
int length = String.valueOf(i).length();
maxLength = Math.max(length, maxLength);
}
List<List<Integer>> list =
new ArrayList<List<Integer>>() {
{
// 0-9
for (int i = 0; i < 10; i++) {
add(new ArrayList<>());
}
}
};
for (int i = 0, temp = 1; i < maxLength; temp *= 10, i++) {
for (int value : clone) {
list.get((value / temp) % 10).add(value);
}
for (int j = 0, k = 0, l = list.size(); j < l; j++) {
while (!list.get(j).isEmpty()) {
clone[k] = list.get(j).get(0);
list.get(j).remove(0);
k++;
}
}
}
}
桶排序
- 設(shè)置一個(gè)定量的數(shù)組當(dāng)作空桶子。
- 尋訪序列,并且把項(xiàng)目一個(gè)一個(gè)放到對應(yīng)的桶子去。
- 對每個(gè)不是空的桶子進(jìn)行排序。
- 從不是空的桶子里把項(xiàng)目再放回原來的序列中。

/** 桶排序 */
private static int[] bucketSort(int[] clone) {
int maxLength = 0, minLength = 0;
// 最大位數(shù)and最小位數(shù)
for (int i = 0, j = clone.length; i < j; i++) {
int length = String.valueOf(clone[i]).length();
maxLength = Math.max(length, maxLength);
if (i == 0) {
minLength = length;
} else {
minLength = Math.min(length, minLength);
}
}
// 新建一個(gè)桶的集合
List<LinkedList<Integer>> buckets = new ArrayList<>();
for (int i = 0, j = maxLength - minLength + 1; i < j; i++) {
// 新建一個(gè)桶,并將其添加到桶的集合中去。
buckets.add(new LinkedList<>());
}
for (int i : clone) {
int index = String.valueOf(i).length() - 1;
LinkedList<Integer> integers = buckets.get(index);
integers.add(i);
}
int[] finalArr = new int[clone.length];
int tempIndex = 0;
// 計(jì)數(shù)排序
for (LinkedList<Integer> integers : buckets) {
if (integers.size() > 0) {
int max = integers.get(0);
int min = integers.get(0);
for (Integer i : integers) {
if (i > max) {
max = i;
}
if (i < min) {
min = i;
}
}
int dValue = max - min;
int[] countArray = new int[dValue + 1];
for (int value : integers) {
countArray[value - min]++;
}
// 統(tǒng)計(jì)數(shù)組做變形,后邊的元素等于前面的元素之和
for (int i = 1; i < countArray.length; i++) {
countArray[i] += countArray[i - 1];
}
// 倒序遍歷原始數(shù)組,從統(tǒng)計(jì)數(shù)組中找到正確的位置,輸出到結(jié)果數(shù)組
Integer[] sortedArray = new Integer[integers.size()];
for (int i = integers.size() - 1; i >= 0; i--) {
// 給sortedArray的當(dāng)前位置賦值
sortedArray[countArray[integers.get(i) - min] - 1] = integers.get(i);
// 給countArray的位置的值--
countArray[integers.get(i) - min]--;
}
for (Integer integer : sortedArray) {
finalArr[tempIndex++] = integer;
}
}
}
return finalArr;
}
歸并排序
- 把長度為n的輸入序列分成兩個(gè)長度為n/2的子序列;
- 對這兩個(gè)子序列分別采用歸并排序;
- 將兩個(gè)排序好的子序列合并成一個(gè)最終的排序序列。

/**
* 歸并排序
*
* @param ints 數(shù)組
* @param start 左角標(biāo)
* @param end 右角標(biāo)
* @param tempArr 輔助數(shù)組
*/
private static void mergeSort(int[] ints, int start, int end, int[] tempArr) {
// 當(dāng)子序列中只有一個(gè)元素時(shí)結(jié)束遞歸
if (start < end) {
// 劃分子序列
int mid = (start + end) / 2;
// 對左側(cè)子序列進(jìn)行遞歸排序
mergeSort(ints, start, mid, tempArr);
// 對右側(cè)子序列進(jìn)行遞歸排序
mergeSort(ints, mid + 1, end, tempArr);
// 合并
merge(ints, start, mid, end, tempArr);
}
}
/** 兩路歸并算法,兩個(gè)排好序的子序列合并為一個(gè)子序列 */
private static void merge(int[] ints, int left, int mid, int right, int[] tempArr) {
int p1 = left, p2 = mid + 1, k = left;
while (p1 <= mid && p2 <= right) {
if (ints[p1] <= ints[p2]) {
tempArr[k++] = ints[p1++];
} else {
tempArr[k++] = ints[p2++];
}
}
while (p1 <= mid) {
// 如果第一個(gè)序列未檢測完,直接將后面所有元素加到合并的序列中
tempArr[k++] = ints[p1++];
}
while (p2 <= right) {
tempArr[k++] = ints[p2++];
}
// 復(fù)制回原素組
if (right + 1 - left >= 0) {
System.arraycopy(tempArr, left, ints, left, right + 1 - left);
}
}
希爾排序
- 選擇一個(gè)增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列個(gè)數(shù)k,對序列進(jìn)行k 趟排序;
- 每趟排序,根據(jù)對應(yīng)的增量ti,將待排序列分割成若干長度為m 的子序列,分別對各子表進(jìn)行直接插入排序。僅增量因子為1 時(shí),整個(gè)序列作為一個(gè)表來處理,表長度即為整個(gè)序列的長度。

/** 希爾排序 */
public static void shellSort(int[] clone) {
// 步長逐漸減小
for (int gap = clone.length / 2; gap > 0; gap /= 2) {
// 在同一步長內(nèi)
for (int i = gap; i < clone.length; i++) {
// 同一步長內(nèi)排序方式是插入排序
int temp = clone[i], j;
// j-gap代表有序數(shù)組中最大數(shù)的下標(biāo),j-pag表示有序數(shù)組的前一個(gè)元素,減pag是減去偏移量就是步長
for (j = i; j >= gap && temp < clone[j - gap]; j -= gap) {
// 原有序數(shù)組最大的后移一位
clone[j] = clone[j - gap];
}
// 找到了合適的位置插入
clone[j] = temp;
}
}
}
堆排序
- 將初始待排序關(guān)鍵字序列(R1,R2….Rn)構(gòu)建成大頂堆,此堆為初始的無序區(qū);
- 將堆頂元素R[1]與最后一個(gè)元素R[n]交換,此時(shí)得到新的無序區(qū)(R1,R2,……Rn-1)和新的有序區(qū)(Rn),且滿足R[1,2…n-1]<=R[n];
- 由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對當(dāng)前無序區(qū)(R1,R2,……Rn-1)調(diào)整為新堆,然后再次將R[1]與無序區(qū)最后一個(gè)元素交換,得到新的無序區(qū)(R1,R2….Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復(fù)此過程直到有序區(qū)的元素個(gè)數(shù)為n-1,則整個(gè)排序過程完成。

/** 堆排序 */
private static void heapSort(int[] clone) {
// 創(chuàng)建堆
for (int i = (clone.length - 1) / 2; i >= 0; i--) {
// 從第一個(gè)非葉子結(jié)點(diǎn)從下至上,從右至左調(diào)整結(jié)構(gòu)
adjustHeap(clone, i, clone.length);
}
// 調(diào)整堆結(jié)構(gòu),交換堆頂元素與末尾元素
for (int i = clone.length - 1; i > 0; i--) {
// 將堆頂元素與末尾元素進(jìn)行交換
clone[i] = clone[i]+clone[0];
clone[0] = clone[i]-clone[0];
clone[i] = clone[i]-clone[0];
// 重新對堆進(jìn)行調(diào)整
adjustHeap(clone, 0, i);
}
}
/**
* 調(diào)整堆
*
* @param arr 待排序列
* @param parent 父節(jié)點(diǎn)
* @param length 待排序列尾元素索引
*/
private static void adjustHeap(int[] arr, int parent, int length) {
// 將temp作為父節(jié)點(diǎn)
int temp = arr[parent];
// 左孩子
int lChild = 2 * parent + 1;
while (lChild < length) {
// 右孩子
int rChild = lChild + 1;
// 如果有右孩子結(jié)點(diǎn),并且右孩子結(jié)點(diǎn)的值大于左孩子結(jié)點(diǎn),則選取右孩子結(jié)點(diǎn)
if (rChild < length && arr[lChild] < arr[rChild]) {
lChild++;
}
// 如果父結(jié)點(diǎn)的值已經(jīng)大于孩子結(jié)點(diǎn)的值,則直接結(jié)束
if (temp >= arr[lChild]) {
break;
}
// 把孩子結(jié)點(diǎn)的值賦給父結(jié)點(diǎn)
arr[parent] = arr[lChild];
// 選取孩子結(jié)點(diǎn)的左孩子結(jié)點(diǎn),繼續(xù)向下篩選
parent = lChild;
lChild = 2 * lChild + 1;
}
arr[parent] = temp;
}
練習(xí)代碼
import java.util.*;
/**
* @author: shihchieh.ma
* @create: 2020/6/15 6:13 下午
* @email: shihchieh.ma@gail.com
* @description:
*/
public class Sort {
public static final int[] INTS = {
24, 352, 23, 4, 1, 421, 5, 6, 436, 7, 86, 97, 9, 74, 34, 234, 1, 3, 6, 7
// 10, 8, 6, 4, 2
};
/**
* @param n 生成n個(gè)元素的隨機(jī)數(shù)組
* @param rangeL 隨機(jī)范圍[rangeL
* @param rangeR rangeR]
* @return 返回一個(gè)隨機(jī) int 型數(shù)組
*/
public static int[] gennerateArray(int n, int rangeL, int rangeR) {
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = (int) (Math.random() * (rangeR - rangeL + 1)) + rangeL;
}
return arr;
}
public static void main(String[] args) {
// int[] INTS = gennerateArray(10000, 1,10001);
long startTime, endTime;
// 冒泡排序
int[] bubbleArr = INTS.clone();
startTime = System.currentTimeMillis();
bubbleSort(bubbleArr);
endTime = System.currentTimeMillis();
printArray("冒泡排序:", bubbleArr, endTime - startTime);
// 選擇排序
int[] selectionArr = INTS.clone();
startTime = System.currentTimeMillis();
selectionSort(selectionArr);
endTime = System.currentTimeMillis();
printArray("選擇排序:", selectionArr, endTime - startTime);
// 插入排序
int[] insertArr = INTS.clone();
startTime = System.currentTimeMillis();
insertSort(insertArr);
endTime = System.currentTimeMillis();
printArray("插入排序:", insertArr, endTime - startTime);
// 快速排序
int[] quickArr = INTS.clone();
startTime = System.currentTimeMillis();
quickSort(quickArr, 0, quickArr.length - 1);
endTime = System.currentTimeMillis();
printArray("快速排序:", quickArr, endTime - startTime);
// 計(jì)數(shù)排序
int[] countArr = INTS.clone();
startTime = System.currentTimeMillis();
int[] countSort = countSort(countArr);
endTime = System.currentTimeMillis();
printArray("計(jì)數(shù)排序:", countSort, endTime - startTime);
// 基數(shù)排序
int[] radixArr = INTS.clone();
startTime = System.currentTimeMillis();
radixSort(radixArr);
endTime = System.currentTimeMillis();
printArray("基數(shù)排序:", radixArr, endTime - startTime);
// 桶排序
int[] bucketArr = INTS.clone();
startTime = System.currentTimeMillis();
int[] bucketSort = bucketSort(bucketArr);
endTime = System.currentTimeMillis();
printArray("桶排序:", bucketSort, endTime - startTime);
// 歸并排序
int[] mergeArr = INTS.clone();
startTime = System.currentTimeMillis();
mergeSort(mergeArr, 0, mergeArr.length - 1, new int[mergeArr.length]);
endTime = System.currentTimeMillis();
printArray("歸并排序:", mergeArr, endTime - startTime);
// 希爾排序
int[] shellArr = INTS.clone();
startTime = System.currentTimeMillis();
mergeSort(shellArr, 0, shellArr.length - 1, new int[shellArr.length]);
endTime = System.currentTimeMillis();
printArray("希爾排序:", shellArr, endTime - startTime);
// 堆排序
int[] heapArr = INTS.clone();
startTime = System.currentTimeMillis();
heapSort(heapArr);
endTime = System.currentTimeMillis();
printArray("堆排序:", heapArr, endTime - startTime);
}
/** 冒泡排序 */
private static void bubbleSort(int[] clone) {
for (int i = 0, j = clone.length; i < j; i++) {
for (int k = 0, l = j - 1 - i; k < l; k++) {
if (clone[k] > clone[k + 1]) {
clone[k] = clone[k] ^ clone[k + 1];
clone[k + 1] = clone[k] ^ clone[k + 1];
clone[k] = clone[k] ^ clone[k + 1];
}
}
}
}
/** 選擇排序 */
private static void selectionSort(int[] clone) {
for (int i = 0, j = clone.length; i < j; i++) {
int minIndex = i;
for (int k = i; k < j; k++) {
if (clone[k] < clone[minIndex]) {
minIndex = k;
}
}
if (minIndex != i) {
clone[i] = clone[i] + clone[minIndex];
clone[minIndex] = clone[i] - clone[minIndex];
clone[i] = clone[i] - clone[minIndex];
}
}
}
/** 插入排序 */
private static void insertSort(int[] clone) {
for (int i = 1, j = clone.length; i < j; i++) {
int k = i;
int temp = clone[k];
while (k > 0 && clone[k - 1] > temp) {
clone[k] = clone[k - 1];
k--;
}
clone[k] = temp;
}
}
/**
* 快速排序
*
* @param clone 數(shù)組
* @param leftIndex 左邊角標(biāo) 初始0
* @param rightIndex 右邊角標(biāo) 初始length-1
*/
private static void quickSort(int[] clone, int leftIndex, int rightIndex) {
// temp-基準(zhǔn)位
int i, j, temp;
if (leftIndex > rightIndex) {
return;
}
i = leftIndex;
j = rightIndex;
temp = clone[leftIndex];
while (i < j) {
// 先右邊,往左遞減,找一個(gè)小于基準(zhǔn)位的數(shù)
// 當(dāng)右邊的角標(biāo)位置所在的數(shù)>基準(zhǔn)位的數(shù)時(shí),繼續(xù)從右往左找(同時(shí) j 索引-1)
// 找到就跳出 while循環(huán)
while (temp <= clone[j] && i < j) {
j--;
}
// 再左邊,往右遞增
// 如上
while (temp >= clone[i] && i < j) {
i++;
}
// 滿足條件則交換
if (i < j) {
clone[i] = clone[i] + clone[j];
clone[j] = clone[i] - clone[j];
clone[i] = clone[i] - clone[j];
}
}
// i=j 左右在同一位置
// 最后將基準(zhǔn)為與i和j相等位置的數(shù)字交換
clone[leftIndex] = clone[i];
clone[i] = temp;
// 左半數(shù)組<(i或j所在索引的數(shù))<右半數(shù)組
// 也就是說(i或j所在索引的數(shù))已經(jīng)確定排序位置,就不用再排序了,
// 相同的方法分別處理左右數(shù)組
// 遞歸調(diào)用左半數(shù)組
quickSort(clone, leftIndex, j - 1);
// 遞歸調(diào)用右半數(shù)組
quickSort(clone, j + 1, rightIndex);
}
/** 計(jì)數(shù)排序 */
private static int[] countSort(int[] clone) {
int max = clone[0];
int min = clone[0];
for (int i = 1, j = clone.length; i < j; i++) {
if (clone[i] > max) {
max = clone[i];
}
if (clone[i] < min) {
min = clone[i];
}
}
int dValue = max - min;
int[] countArray = new int[dValue + 1];
for (int value : clone) {
countArray[value - min]++;
}
// 統(tǒng)計(jì)數(shù)組做變形,后邊的元素等于前面的元素之和
for (int i = 1; i < countArray.length; i++) {
countArray[i] += countArray[i - 1];
}
// 倒序遍歷原始數(shù)組,從統(tǒng)計(jì)數(shù)組中找到正確的位置,輸出到結(jié)果數(shù)組
int[] sortedArray = new int[clone.length];
for (int i = clone.length - 1; i >= 0; i--) {
// 給sortedArray的當(dāng)前位置賦值
sortedArray[countArray[clone[i] - min] - 1] = clone[i];
// 給countArray的位置的值--
countArray[clone[i] - min]--;
}
return sortedArray;
}
/** 基數(shù)排序 */
private static void radixSort(int[] clone) {
int maxLength = 0;
// 最大位數(shù)
for (int i : clone) {
int length = String.valueOf(i).length();
maxLength = Math.max(length, maxLength);
}
List<List<Integer>> list =
new ArrayList<List<Integer>>() {
{
// 0-9
for (int i = 0; i < 10; i++) {
add(new ArrayList<>());
}
}
};
for (int i = 0, temp = 1; i < maxLength; temp *= 10, i++) {
for (int value : clone) {
list.get((value / temp) % 10).add(value);
}
for (int j = 0, k = 0, l = list.size(); j < l; j++) {
while (!list.get(j).isEmpty()) {
clone[k] = list.get(j).get(0);
list.get(j).remove(0);
k++;
}
}
}
}
/** 桶排序 */
private static int[] bucketSort(int[] clone) {
int maxLength = 0, minLength = 0;
// 最大位數(shù)and最小位數(shù)
for (int i = 0, j = clone.length; i < j; i++) {
int length = String.valueOf(clone[i]).length();
maxLength = Math.max(length, maxLength);
if (i == 0) {
minLength = length;
} else {
minLength = Math.min(length, minLength);
}
}
// 新建一個(gè)桶的集合
List<LinkedList<Integer>> buckets = new ArrayList<>();
for (int i = 0, j = maxLength - minLength + 1; i < j; i++) {
// 新建一個(gè)桶,并將其添加到桶的集合中去。
buckets.add(new LinkedList<>());
}
for (int i : clone) {
int index = String.valueOf(i).length() - 1;
LinkedList<Integer> integers = buckets.get(index);
integers.add(i);
}
int[] finalArr = new int[clone.length];
int tempIndex = 0;
// 計(jì)數(shù)排序
for (LinkedList<Integer> integers : buckets) {
if (integers.size() > 0) {
int max = integers.get(0);
int min = integers.get(0);
for (Integer i : integers) {
if (i > max) {
max = i;
}
if (i < min) {
min = i;
}
}
int dValue = max - min;
int[] countArray = new int[dValue + 1];
for (int value : integers) {
countArray[value - min]++;
}
// 統(tǒng)計(jì)數(shù)組做變形,后邊的元素等于前面的元素之和
for (int i = 1; i < countArray.length; i++) {
countArray[i] += countArray[i - 1];
}
// 倒序遍歷原始數(shù)組,從統(tǒng)計(jì)數(shù)組中找到正確的位置,輸出到結(jié)果數(shù)組
Integer[] sortedArray = new Integer[integers.size()];
for (int i = integers.size() - 1; i >= 0; i--) {
// 給sortedArray的當(dāng)前位置賦值
sortedArray[countArray[integers.get(i) - min] - 1] = integers.get(i);
// 給countArray的位置的值--
countArray[integers.get(i) - min]--;
}
for (Integer integer : sortedArray) {
finalArr[tempIndex++] = integer;
}
}
}
return finalArr;
}
/**
* 歸并排序
*
* @param ints 數(shù)組
* @param start 左角標(biāo)
* @param end 右角標(biāo)
* @param tempArr 輔助數(shù)組
*/
private static void mergeSort(int[] ints, int start, int end, int[] tempArr) {
// 當(dāng)子序列中只有一個(gè)元素時(shí)結(jié)束遞歸
if (start < end) {
// 劃分子序列
int mid = (start + end) / 2;
// 對左側(cè)子序列進(jìn)行遞歸排序
mergeSort(ints, start, mid, tempArr);
// 對右側(cè)子序列進(jìn)行遞歸排序
mergeSort(ints, mid + 1, end, tempArr);
// 合并
merge(ints, start, mid, end, tempArr);
}
}
/** 兩路歸并算法,兩個(gè)排好序的子序列合并為一個(gè)子序列 */
private static void merge(int[] ints, int left, int mid, int right, int[] tempArr) {
int p1 = left, p2 = mid + 1, k = left;
while (p1 <= mid && p2 <= right) {
if (ints[p1] <= ints[p2]) {
tempArr[k++] = ints[p1++];
} else {
tempArr[k++] = ints[p2++];
}
}
while (p1 <= mid) {
// 如果第一個(gè)序列未檢測完,直接將后面所有元素加到合并的序列中
tempArr[k++] = ints[p1++];
}
while (p2 <= right) {
tempArr[k++] = ints[p2++];
}
// 復(fù)制回原素組
if (right + 1 - left >= 0) {
System.arraycopy(tempArr, left, ints, left, right + 1 - left);
}
}
/** 希爾排序 */
private static void shellSort(int[] clone) {
// 步長逐漸減小
for (int gap = clone.length / 2; gap > 0; gap /= 2) {
// 在同一步長內(nèi)
for (int i = gap; i < clone.length; i++) {
// 同一步長內(nèi)排序方式是插入排序
int temp = clone[i], j;
// j-gap代表有序數(shù)組中最大數(shù)的下標(biāo),j-pag表示有序數(shù)組的前一個(gè)元素,減pag是減去偏移量就是步長
for (j = i; j >= gap && temp < clone[j - gap]; j -= gap) {
// 原有序數(shù)組最大的后移一位
clone[j] = clone[j - gap];
}
// 找到了合適的位置插入
clone[j] = temp;
}
}
}
/** 堆排序 */
private static void heapSort(int[] clone) {
// 創(chuàng)建堆
for (int i = (clone.length - 1) / 2; i >= 0; i--) {
// 從第一個(gè)非葉子結(jié)點(diǎn)從下至上,從右至左調(diào)整結(jié)構(gòu)
adjustHeap(clone, i, clone.length);
}
// 調(diào)整堆結(jié)構(gòu),交換堆頂元素與末尾元素
for (int i = clone.length - 1; i > 0; i--) {
// 將堆頂元素與末尾元素進(jìn)行交換
clone[i] = clone[i]+clone[0];
clone[0] = clone[i]-clone[0];
clone[i] = clone[i]-clone[0];
// 重新對堆進(jìn)行調(diào)整
adjustHeap(clone, 0, i);
}
}
/**
* 調(diào)整堆
*
* @param arr 待排序列
* @param parent 父節(jié)點(diǎn)
* @param length 待排序列尾元素索引
*/
private static void adjustHeap(int[] arr, int parent, int length) {
// 將temp作為父節(jié)點(diǎn)
int temp = arr[parent];
// 左孩子
int lChild = 2 * parent + 1;
while (lChild < length) {
// 右孩子
int rChild = lChild + 1;
// 如果有右孩子結(jié)點(diǎn),并且右孩子結(jié)點(diǎn)的值大于左孩子結(jié)點(diǎn),則選取右孩子結(jié)點(diǎn)
if (rChild < length && arr[lChild] < arr[rChild]) {
lChild++;
}
// 如果父結(jié)點(diǎn)的值已經(jīng)大于孩子結(jié)點(diǎn)的值,則直接結(jié)束
if (temp >= arr[lChild]) {
break;
}
// 把孩子結(jié)點(diǎn)的值賦給父結(jié)點(diǎn)
arr[parent] = arr[lChild];
// 選取孩子結(jié)點(diǎn)的左孩子結(jié)點(diǎn),繼續(xù)向下篩選
parent = lChild;
lChild = 2 * lChild + 1;
}
arr[parent] = temp;
}
private static void printArray(String name, int[] ints, long time) {
for (int anInt : ints) {
System.out.print("_" + anInt + "_");
}
System.out.println("\t");
System.out.println(name + "耗時(shí):" + time);
System.out.println();
}
}