關於常用排序算法的一個總結
阿新 • • 發佈:2018-02-05
ons sta 一次 插入排序 臨時 class except 歸並 exception
前段時間被人問到排序算法,今天特此總結一下,冒泡,選擇,快排,歸並,插入這五種排序算法。
1.選擇排序
選擇排序是整體對比,每次選出你最需要的那個值,比如以下代碼,首先選出最小的值,從小實現從小到大排序,外循環一次,內部循環記錄下最小的坐標,只發生一次交換,它是一種穩定的排序算法,時間復雜度為o(n2),核心代碼如下:
int[] numberArray = { 22, 32, 12, 1, 5, 66 }; int arraylength = numberArray.length; int temp = 0; for (int i = 0; i < arraylength - 1; i++) { int k = i; for (int j = i + 1; j < arraylength; j++) { if (numberArray[k] > numberArray[j]) { k = j; } } if (i != k) { temp = numberArray[i]; numberArray[i] = numberArray[k]; numberArray[k] = temp; } } System.out.println(Arrays.toString(numberArray));
2.冒泡排序
冒泡排序的核心思路是相鄰元素進行對比,把大的數往後移,外循環一次,內部循環可能會發生很多次交換,它是一種穩定的算法,時間復雜度為o(n2),核心代碼如下:
int[] numberArray = { 22, 32, 12, 1, 5, 66 }; int arraylength = numberArray.length; int temp = 0; for (int i = 0; i < arraylength - 1; i++) { for (int j = i + 1; j < arraylength; j++) {if (numberArray[i] > numberArray[j]) { temp = numberArray[i]; numberArray[i] = numberArray[j]; numberArray[j] = temp; } } } System.out.println(Arrays.toString(numberArray));
3.插入排序
插入排序通過默認一個正確的位置,然後尋找插入位置,有點像我們完鬥地主時,會把連牌挨著大小放著,它也是一種穩定的排序算法,時間復雜度為o(n2 ),核心代碼如下:
int[] numberArray = { 22, 32, 12, 1, 5, 66 }; for (int i = 1; i < numberArray.length; i++) { ////把j看作一個遊標 int j = i; int target = numberArray[i]; while (j > 0 && target < numberArray[j - 1]) { //// 說明有更大的,往後移 numberArray[j] = numberArray[j - 1]; j--; } numberArray[j] = target; } System.out.println(Arrays.toString(numberArray));
4.快速排序
快速排序的核心是冒泡+二分+遞歸分治,實際應用中算是最好的排序算法了,但它是一種不穩定的排序算法,平均時間復雜度為o(nlgn),最壞的情況是o(n2),它和冒泡算法的區別是同時查找大的數和小的數,核心代碼如下:
public static void main(String[] args) { try { int[] numberArray = new int[] { 4, 3, 6, 1, 2, 5 }; recursionSort(numberArray, 0, numberArray.length - 1); System.out.println(Arrays.toString(numberArray)); } catch (Exception ex) { System.out.println(ex.getMessage()); } } private static void recursionSort(int[] numberArray, int low, int high) { if (low < high) { int basevalueIndex = partitionGroup(numberArray, low, high); ////左區間遞歸 recursionSort(numberArray, low, basevalueIndex - 1); ////右區間遞歸 recursionSort(numberArray, basevalueIndex + 1, high); } } private static int partitionGroup(int[] numberArray, int low, int high) { int basevalue = numberArray[low]; while (low < high) { //// 先從右向左 while (low < high && numberArray[high] >= basevalue) { --high; } //// 交換比基準值小的到左邊 numberArray[low] = numberArray[high]; while (low < high && numberArray[low] <= basevalue) { ++low; } //// 交互比基準值大的到右邊 numberArray[high] = numberArray[low]; } //// 掃描完成,左右下標,即low=high numberArray[low] = basevalue; //// 返回基準值的下標 return low; }
5.歸並排序
理論上歸並排序的效率應該高於快速排序,但是由於賦值次數較多以及分配臨時數組等,所以和快排的效率應該不相上下。它的思路就是把原始數組序列不斷兩兩分塊,直到每一個塊只剩下一個元素,然後利用遞歸的原理合並即可,它是一種穩定的排序算法,時間復雜度為o(n2),核心代碼如下:
public static void main(String[] args) { try { int[] numberArray = new int[] { 4, 3, 6, 1, 2, 5 }; partition(numberArray, 0, numberArray.length - 1); } catch (Exception ex) { System.out.println(ex.getMessage()); } } public static void partition(int[] a, int low, int high) { int mid = (low + high) / 2; if (low < high) { // 左邊 partition(a, low, mid); // 右邊 partition(a, mid + 1, high); // 左右歸並 merge(a, low, mid, high); System.out.println(Arrays.toString(a)); } } public static void merge(int[] numberArray, int low, int mid, int high) { int[] temp = new int[high - low + 1]; //// 左指針 int i = low; // 右指針 int j = mid + 1; int k = 0; // 把較小的數先移到新數組中 while (i <= mid && j <= high) { if (numberArray[i] < numberArray[j]) { temp[k++] = numberArray[i++]; } else { temp[k++] = numberArray[j++]; } } // 把左邊剩余的數移入數組 while (i <= mid) { temp[k++] = numberArray[i++]; } // 把右邊邊剩余的數移入數組 while (j <= high) { temp[k++] = numberArray[j++]; } // 把新數組中的數覆蓋nums數組 for (int k2 = 0; k2 < temp.length; k2++) { numberArray[k2 + low] = temp[k2]; } }
關於常用排序算法的一個總結