十大經典排序演算法Java實現
阿新 • • 發佈:2019-02-12
import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; public class Sort { public static int[] getIntArr(int length) { int[] arr = new int[length]; for (int i = 0; i < arr.length; i++) { arr[i] = (int) (Math.random()*length); } return arr; } public static ArrayList<Integer> getIntArrayList(int length) { ArrayList<Integer> arr = new ArrayList<>(length); for (int i = 0; i < length; i++) { arr.add((int) (Math.random()*length)); } return arr; } public static void main(String[] args) { LocalDateTime start = null; LocalDateTime end = null; //氣泡排序 int[] bubbleSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(bubbleSort)); start = LocalDateTime.now(); bubbleSort(bubbleSort); end = LocalDateTime.now(); System.out.println("氣泡排序結果:"+Arrays.toString(bubbleSort(bubbleSort))); System.out.println("氣泡排序用時:"+Duration.between(start, end).toNanos()); //選擇排序 int[] selectionSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(selectionSort)); start = LocalDateTime.now(); selectionSort(selectionSort); end = LocalDateTime.now(); System.out.println("選擇排序結果:"+Arrays.toString(selectionSort(selectionSort))); System.out.println("選擇排序用時:"+Duration.between(start, end).toNanos()); //插入排序 int[] insertionSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(insertionSort)); start = LocalDateTime.now(); insertionSort(insertionSort); end = LocalDateTime.now(); System.out.println("插入排序結果:"+Arrays.toString(insertionSort(insertionSort))); System.out.println("插入排序用時:"+Duration.between(start, end).toNanos()); //希爾排序 int[] shellSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(shellSort)); start = LocalDateTime.now(); shellSort(shellSort); end = LocalDateTime.now(); System.out.println("希爾排序結果:"+Arrays.toString(shellSort(shellSort))); System.out.println("希爾排序用時:"+Duration.between(start, end).toNanos()); //歸併排序 int[] mergeSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(mergeSort)); start = LocalDateTime.now(); mergeSort(mergeSort); end = LocalDateTime.now(); System.out.println("歸併排序結果:"+Arrays.toString(mergeSort(mergeSort))); System.out.println("歸併排序用時:"+Duration.between(start, end).toNanos()); //快速排序 int[] quickSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(quickSort)); start = LocalDateTime.now(); quickSort(quickSort, 0, quickSort.length-1); end = LocalDateTime.now(); System.out.println("快速排序結果:"+Arrays.toString(quickSort)); System.out.println("快速排序用時:"+Duration.between(start, end).toNanos()); //記數排序 int[] countingSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(countingSort)); start = LocalDateTime.now(); countingSort(countingSort); end = LocalDateTime.now(); System.out.println("記數排序結果:"+Arrays.toString(countingSort)); System.out.println("記數排序用時:"+Duration.between(start, end).toNanos()); //基數排序 int[] radixSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(radixSort)); start = LocalDateTime.now(); radixSort(radixSort); end = LocalDateTime.now(); System.out.println("基數排序結果:"+Arrays.toString(radixSort)); System.out.println("基數排序用時:"+Duration.between(start, end).toNanos()); //堆排序 int[] heapSort = getIntArr(1000); System.out.println("原陣列:"+Arrays.toString(heapSort)); start = LocalDateTime.now(); heapSort(heapSort); end = LocalDateTime.now(); System.out.println("堆排序結果:"+Arrays.toString(heapSort)); System.out.println("堆排序用時:"+Duration.between(start, end).toNanos()); //bucketSort ArrayList<Integer> bucketSort = getIntArrayList(1000); System.out.println("原陣列:"+bucketSort); start = LocalDateTime.now(); bucketSort(bucketSort,bucketSort.size()); end = LocalDateTime.now(); System.out.println("堆排序結果:"+bucketSort); System.out.println("堆排序用時:"+Duration.between(start, end).toNanos()); } /** * 氣泡排序,升序 * @param arr 需要排序的陣列 * @return 排序後的陣列 */ public static int[] bubbleSort(int[] arr) { int temp = 0; int length = arr.length; for (int i = 0; i < length-1; i++) { for (int j = 0; j < length-1-i; j++) { //相鄰兩個比較,如果前面大於後面。進行交換。升序 if(arr[j]>arr[j+1]) { temp = arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } return arr; } /** * 選擇排序 * * @param arr 需要排序的陣列 * @return 排序後的陣列 */ public static int[] selectionSort(int[] arr) { int temp = 0; int length = arr.length; for (int i = 0; i < length-1; i++) { int minIndex = i; for (int j = i+1; j < length; j++) { if(arr[j]<arr[minIndex]) { minIndex = j; } } temp = arr[i]; arr[i]=arr[minIndex]; arr[minIndex]=temp; } return arr; } /** * 插入排序 * * @param arr 需要排序的陣列 * @return 排序後的陣列 */ public static int[] insertionSort(int[] arr) { int current = 0; int preIndex = 0; int length = arr.length; for (int i = 1; i < length; i++) { preIndex = i-1; current = arr[i]; while(preIndex>=0&&arr[preIndex]>current) { arr[preIndex+1] = arr[preIndex]; preIndex--; } arr[preIndex+1] = current; } return arr; } /** * 希爾排序 * * @param array * @return */ public static int[] shellSort(int[] array) { int len = array.length; int temp, gap = len / 2; while (gap > 0) { for (int i = gap; i < len; i++) { temp = array[i]; int preIndex = i - gap; while (preIndex >= 0 && array[preIndex] > temp) { array[preIndex + gap] = array[preIndex]; preIndex -= gap; } array[preIndex + gap] = temp; } gap /= 2; } return array; } /** * 歸併排序 * * @param array * @return */ public static int[] mergeSort(int[] array) { if (array.length < 2) return array; int mid = array.length / 2; int[] left = Arrays.copyOfRange(array, 0, mid); int[] right = Arrays.copyOfRange(array, mid, array.length); return merge(mergeSort(left), mergeSort(right)); } /** * 歸併排序——將兩段排序好的陣列結合成一個排序陣列 * * @param left * @param right * @return */ public static int[] merge(int[] left, int[] right) { int[] result = new int[left.length + right.length]; for (int index = 0, i = 0, j = 0; index < result.length; index++) { if (i >= left.length) result[index] = right[j++]; else if (j >= right.length) result[index] = left[i++]; else if (left[i] > right[j]) result[index] = right[j++]; else result[index] = left[i++]; } return result; } /** * 快速排序方法 * @param array * @param start * @param end * @return */ public static int[] quickSort(int[] array, int start, int end) { if (array.length < 1 || start < 0 || end >= array.length || start > end) return null; int smallIndex = partition(array, start, end); if (smallIndex > start) quickSort(array, start, smallIndex - 1); if (smallIndex < end) quickSort(array, smallIndex + 1, end); return array; } /** * 快速排序演算法——partition * @param array * @param start * @param end * @return */ public static int partition(int[] array, int start, int end) { int pivot = (int) (start + Math.random() * (end - start + 1)); int smallIndex = start - 1; swap(array, pivot, end); for (int i = start; i <= end; i++) if (array[i] <= array[end]) { smallIndex++; if (i > smallIndex) swap(array, i, smallIndex); } return smallIndex; } /** * 交換陣列內兩個元素 * @param array * @param i * @param j */ public static void swap(int[] array, int i, int j) { int temp = array[i]; array[i] = array[j]; array[j] = temp; } /** * 計數排序 * * @param array * @return */ public static int[] countingSort(int[] array) { if (array.length == 0) return array; int bias, min = array[0], max = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] > max) max = array[i]; if (array[i] < min) min = array[i]; } bias = 0 - min; int[] bucket = new int[max - min + 1]; Arrays.fill(bucket, 0); for (int i = 0; i < array.length; i++) { bucket[array[i] + bias]++; } int index = 0, i = 0; while (index < array.length) { if (bucket[i] != 0) { array[index] = i - bias; bucket[i]--; index++; } else i++; } return array; } /** * 桶排序 * * @param array * @param bucketSize * @return */ public static ArrayList<Integer> bucketSort(ArrayList<Integer> array, int bucketSize) { if (array == null || array.size() < 2) return array; int max = array.get(0), min = array.get(0); // 找到最大值最小值 for (int i = 0; i < array.size(); i++) { if (array.get(i) > max) max = array.get(i); if (array.get(i) < min) min = array.get(i); } int bucketCount = (max - min) / bucketSize + 1; ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount); ArrayList<Integer> resultArr = new ArrayList<>(); for (int i = 0; i < bucketCount; i++) { bucketArr.add(new ArrayList<Integer>()); } for (int i = 0; i < array.size(); i++) { bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i)); } for (int i = 0; i < bucketCount; i++) { if (bucketSize == 1) { // 如果帶排序陣列中有重複數字時 感謝 @見風任然是風 朋友指出錯誤 for (int j = 0; j < bucketArr.get(i).size(); j++) resultArr.add(bucketArr.get(i).get(j)); } else { if (bucketCount == 1) bucketSize--; ArrayList<Integer> temp = bucketSort(bucketArr.get(i), bucketSize); for (int j = 0; j < temp.size(); j++) resultArr.add(temp.get(j)); } } return resultArr; } /** * 基數排序 * @param array * @return */ public static int[] radixSort(int[] array) { if (array == null || array.length < 2) return array; // 1.先算出最大數的位數; int max = array[0]; for (int i = 1; i < array.length; i++) { max = Math.max(max, array[i]); } int maxDigit = 0; while (max != 0) { max /= 10; maxDigit++; } int mod = 10, div = 1; ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>(); for (int i = 0; i < 10; i++) bucketList.add(new ArrayList<Integer>()); for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) { for (int j = 0; j < array.length; j++) { int num = (array[j] % mod) / div; bucketList.get(num).add(array[j]); } int index = 0; for (int j = 0; j < bucketList.size(); j++) { for (int k = 0; k < bucketList.get(j).size(); k++) array[index++] = bucketList.get(j).get(k); bucketList.get(j).clear(); } } return array; } //宣告全域性變數,用於記錄陣列array的長度; static int len; /** * 堆排序演算法 * * @param array * @return */ public static int[] heapSort(int[] array) { len = array.length; if (len < 1) return array; //1.構建一個最大堆 buildMaxHeap(array); //2.迴圈將堆首位(最大值)與末位交換,然後在重新調整最大堆 while (len > 0) { swap(array, 0, len - 1); len--; adjustHeap(array, 0); } return array; } /** * 建立最大堆 * * @param array */ public static void buildMaxHeap(int[] array) { //從最後一個非葉子節點開始向上構造最大堆 for (int i = (len/2 - 1); i >= 0; i--) { //感謝 @讓我發會呆 網友的提醒,此處應該為 i = (len/2 - 1) adjustHeap(array, i); } } /** * 調整使之成為最大堆 * * @param array * @param i */ public static void adjustHeap(int[] array, int i) { int maxIndex = i; //如果有左子樹,且左子樹大於父節點,則將最大指標指向左子樹 if (i * 2 < len && array[i * 2] > array[maxIndex]) maxIndex = i * 2; //如果有右子樹,且右子樹大於父節點,則將最大指標指向右子樹 if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex]) maxIndex = i * 2 + 1; //如果父節點不是最大值,則將父節點與最大值交換,並且遞迴調整與父節點交換的位置。 if (maxIndex != i) { swap(array, maxIndex, i); adjustHeap(array, maxIndex); } } }