前段时间被人问到排序算法,今天特此总结一下,冒泡,选择,快排,归并,插入这五种排序算法。
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]; } }