排序算法集合(java版):網上收集未測試

package test; public class SortUtil { /** * 冒泡排序 Bubble Sort * <p> * 原理: 比較n輪,每一輪都把最大元素移動到數組後端。 * * @return */ public int[] bubbleSort(int[] result) { int ARRAYSIZE = result.length; for (int i = 0; i < ARRAYSIZE; i++) { for (int j = i + 1; j < ARRAYSIZE; j++) { if (result[i] > result[j]) { // 交換 swap(result, i, j); } } } return result; } /** * 插入排序 Insert Sort * <p> * 原理: 從第二個元素開始,因爲左側的數組爲排序後的數組, 只要將當前元素插入到左側數組的適當位置,就能保持數組爲有序 * 然後處理第三個元素...直到最後一個元素 * * @return */ public int[] insertSort(int[] result) { int ARRAYSIZE = result.length; for (int i = 1; i < ARRAYSIZE; i++) { for (int j = i; j > 0 && result[j] < result[j - 1]; j--) { swap(result, j, j - 1); } } return result; } /** * 折半搜索插入排序 BinarySearchThenInsert Sort * <p> * 原理與插入排序類似,不同點在於尋找插入位置的時候,採取的是折半查找方法 * * @return */ public int[] binsertSort(int[] result) { int ARRAYSIZE = result.length; for (int i = 1; i < ARRAYSIZE; i++) { if (result[i] < result[0]) { int temp = result[i]; for (int j = i - 1; j >= 0; j--) { result[j + 1] = result[j]; } result[0] = temp; } else if (result[i] < result[i - 1]) { int larrange = 0; int rarrange = i - 1; while (rarrange - larrange > 1) { int p = (rarrange + larrange + 1) / 2; if (result[i] < result[p]) { rarrange = p; } else { larrange = p; } } int temp = result[i]; for (int j = i - 1; j >= larrange + 1; j--) { result[j + 1] = result[j]; } result[larrange + 1] = temp; } } return result; } /** * 堆排序 Heap Sort * <p> * 原理: 利用了堆的易調整的特點來進行的一種選擇排序。 以大頂堆爲例,什麼是大頂堆? * 大頂堆的邏輯結構是一顆完全二叉樹,[把滿二叉樹最後一層右側的一些葉子摘掉] 假設其高度爲h,則元素個數介於 1 + 2 + ... + * exp(2, h - 2) ~ 1 + 2 + ... + exp(2, h -1)之間 符合如下定義爲大頂堆:(此定義基於大頂堆的順序存儲結構) * for (int i = array.length - 1; i > 0; i --) { 任意 array[i] <= array[(i - * 1)/2]; } (還有一種是小頂堆,不同的只是比較時候的大於號方向不同)。 容易想到,當堆頂元素(MaxValue)被替換後, * 至多只要在雙親和子節點間進行h(大頂堆的高度) - 1次交換, (參照交換算法可以發現比較次數一般來說是交換次數的2~3倍,也不算多) * 就可以形成新的大頂堆。由此大大提高了排序效率。 * * @return */ public int[] heapSort(int[] result) { // 初始化無序數組爲大頂堆 for (int i = result.length - 2; i >= 0; i--) { adjustHeap(result, i, result.length - 1); } // 將最大值元素交換至數組末端,並調整前端爲大頂堆,循環直至前端只剩下一個元素 for (int i = result.length - 1; i > 0; i--) { swap(result, 0, i); adjustHeap(result, 0, i - 1); } return result; } /** * 將除頂(不確定是否滿足大頂堆條件)外,左子樹和右子樹都爲一個堆的數組調整爲大頂堆 * * @param array * 待調整數組 * @param from * 頂的指針 * @param to * 調整的末端(就是調整array[from]...array[to]這一段爲一個大頂堆) */ private void adjustHeap(int[] array, int from, int to) { int i = 0; // 比較節省比較次數的方法,只要比較到比其左右子樹的根結點的值都大,就可以return了 while (from + 2 * i + 2 <= to) { if (array[from + i] < array[from + 2 * i + 1] || array[from + i] < array[from + 2 * i + 2]) { if (array[from + 2 * i + 1] > array[from + 2 * i + 2]) { swap(array, from + i, from + 2 * i + 1); i += i + 1; } else { swap(array, from + i, from + 2 * i + 2); i += i + 2; } } else { return; } } if (from + 2 * i + 1 == to && array[from + i] < array[from + 2 * i + 1]) { // 有時會出現僅存在左子樹的情況(左子樹爲調整數組的最後一個元素) swap(array, from + i, from + 2 * i + 1); } } /** * 快速排序 Quick Sort * <p> * 原理: 選擇數組中的一個元素作爲標準,將所有比標準小的元素放到左邊, 所有比標準大的元素放到右邊。 並對左邊和右邊的元素做一樣的快速排序過程。 * * @return */ public int[] quickSort(int[] result) { quick(result, 0, result.length - 1); return result; } /** * 選擇數組中的一個元素作爲標準,將所有比標準小的元素放到左邊, 所有比標準大的元素放到右邊。 並對左邊和右邊的元素做一樣的快速排序過程。 * * @param array * @param startIndex * @param endIndex */ private void quick(int[] array, int startIndex, int endIndex) { int pIndex = startIndex; for (int i = startIndex + 1; i <= endIndex; i++) { if (array[i] < array[pIndex]) { int temp = array[i]; for (int j = i; j > pIndex; j--) { array[j] = array[j - 1]; } array[pIndex] = temp; pIndex++; } } if (pIndex - startIndex > 1) { quick(array, startIndex, pIndex - 1); } if (endIndex - pIndex > 1) { quick(array, pIndex + 1, endIndex); } } /** * 歸併排序 Merge Sort * <p> * 原理: 分治。將數組分爲左,右兩部分, 首先將數組分爲左右兩部分,分別進行歸併排序, 然後合併左右兩部分的排序結果就構成了一個有序數組。 * * @return */ public int[] mergeSort(int[] result) { mergeR(result, 0, result.length - 1); return result; } /** * 遞歸對數組進行歸併排序 * * @param array * @param startIndex * @param endIndex */ private void mergeR(int[] array, int startIndex, int endIndex) { if (startIndex < endIndex) { int mid = (startIndex + endIndex) / 2; // 對包括中點在內的左側數組區間進行歸併排序 mergeR(array, startIndex, mid); // 對中點之後的右側數組區間進行歸併排序 mergeR(array, mid + 1, endIndex); // 合併左和右兩個獨立的有序區間爲一個有序區間 merge(array, startIndex, mid, endIndex); } } /** * 將array數組的兩個有序區間array[startIndex]...array[midIndex] 和array[midIndex + * 1]...array[endIndex]合併爲一個有序區間 array[startIndex]...array[endIndex] * * @param array * @param startIndex * @param midIndex * @param endIndex */ private void merge(int[] array, int startIndex, int midIndex, int endIndex) { int[] resultTemp = new int[endIndex - startIndex + 1]; int pr = 0; int p1 = startIndex; int p2 = midIndex + 1; while (p1 <= midIndex || p2 <= endIndex) { if (p1 == midIndex + 1) { while (p2 <= endIndex) { resultTemp[pr++] = array[p2++]; } } else if (p2 == endIndex + 1) { while (p1 <= midIndex) { resultTemp[pr++] = array[p1++]; } } else if (array[p1] <= array[p2]) { resultTemp[pr++] = array[p1++]; } else { resultTemp[pr++] = array[p2++]; } } for (p1 = startIndex, p2 = 0; p1 <= endIndex; p1++, p2++) { array[p1] = resultTemp[p2]; } } /** * 希爾排序 Shell Sort * <p> * 原理: 分別以數組大小的1/2,1/4,1/8....1的作爲步伐d, 將array[i],array[i + d],array[i + * 2d]....array[i + nd]看作一個數組進行排序, 與插入排序相比,因爲可以更有效的消除逆序,因此交換次數是很少的, * 缺點是比較次數過多 * * @return */ public int[] shellSort(int[] result) { int ARRAYSIZE = result.length; for (int d = ARRAYSIZE / 2; d > 0; d = d / 2) { // print(result); for (int i = d; i < ARRAYSIZE; i++) { for (int j = i; j >= d; j = j - d) { if (result[j] < result[j - d]) { swap(result, j, j - d); } } } } return result; } /** * 簡單選擇排序 SimpleSelection Sort * <p> * 原理:每遍歷未排序部分一次都選出一個最小值,並將最小值元素移動到數組前端 * * @return */ public int[] simpleSelectionSort(int[] result) { // 重複此過程:選取最小值,並將其交換至數組前端 int minIndex = 0; for (int i = 0; i < result.length; i++) { minIndex = i; for (int j = i + 1; j < result.length; j++) { if (result[j] < result[minIndex]) { minIndex = j; } } swap(result, minIndex, i); } return result; } /** * 交換元素 */ private void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章