排序算法
1. 冒泡排序
最基础排序,一句话总结冒泡排序,对于给定的数组,如果是升序排序,每一趟排序,都会把最大的元素放置在当前趟次的最后位置;
冒泡排序,只会比较交换两个相邻的元素
时间复杂度:严格O(N^2) ,和数据无关;
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// details O(N^2) Deprecated
// end is arr.length - 1 because exist of swap i++, prevent out of index error situation happen
// outer foreach find one max num, and put it at end of arr array
// inner foreach compare two nums and swap, util to the end of end border
for (int end = arr.length - 1; end > 0; end--) {
for (int i = 0; i < end; i++) {
swap(arr, i, i + 1);
}
}
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
2. 选择排序
最基础排序,一句话总结选择排序,对于给定的数组,如果是升序排序,每次选择最小的元素放置在当前次序的第一个位置;
时间复杂度:严格O(N^2) ,和数据无关;
public static void selectionSort(int[] arr) { if (arr == null || arr.length < 2) { return; } // details O(N^2) Deprecated // first loop: search 0~ N-1, find min num and put it at 0 index // second loop: search 1~ N-1,find min num and put it at 1 index // until foreach all array for (int i = 0; i < arr.length - 1; i++) { int minIndex = i; for (int j = i + 1; j < arr.length; j++) { minIndex = arr[j] < arr[minIndex] ? j : minIndex; } swap(arr, i, minIndex); } } private static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
3. 插入排序
基础排序,类似扑克牌,整体思路如下(升序排)
1. 从第二个元素开始遍历,即index = 1,1个元素默认有序;
2. 对于当前元素,如果前一个元素比当前元素小,那么交换,直到前面没有元素;
3. 每次循环保证当前位置 i 之前的素有元素都是有序的;
时间复杂度:O(N^2)
1. 最好情况:如果原始数据是升序,那么插入排序的时间复杂度是O(N),因为每次都不用发生交换动作;
2. 最坏情况:如果原始数据是逆序,那么插入排序的时间复杂度是O(N^2) ,每次都要进行交换到第一个元素;
public static void insertSort(int[] arr) { if (arr == null || arr.length < 2) { return; } // details for (int i = 1; i < arr.length; i++) { int j = i - 1; while (j > 0 && arr[j] > arr[j + 1]) { swap(arr, j, j + 1); j--; } } } private static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }
4. 归并排序
public void mergeSort(int[] arr) { if (arr == null || arr.length < 2) { return; } process1(arr, 0, arr.length - 1); } private void process1(int[] arr, int start, int end) { if (start == end) { return; } int mid = start + (end - start) / 2; process1(arr, start, mid); process1(arr, mid + 1, end); merge(arr, start, mid, end); } private void merge(int[] arr, int start, int mid, int end) { int[] help = new int[end - start + 1]; int index = 0; int p1 = start; int p2 = mid + 1; while (p1 <= mid && p2 <= end) { help[index++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= mid) { help[index++] = arr[p1++]; } while (p2 <= end) { help[index++] = arr[p2++]; } for (int i = 0; i < help.length; i++) { arr[start + i] = help[i]; } }
5. 归并排序
public void quickSort(int[] arr) { if (arr == null || arr.length < 2) { return; } process(arr, 0, arr.length - 1); } private void process(int[] arr, int start, int end) { if (start >= end) { return; } swap(arr, new Random().nextInt(end - start + 1) + start, end); int[] bound = partition(arr, start, end); process(arr, start, bound[0] - 1); process(arr, bound[1] + 1, end); } private int[] partition(int[] arr, int start, int end) { if (start > end) { return new int[]{-1, -1}; } if (start == end) { return new int[]{start, end}; } int p1 = start - 1; int p2 = end; int index = start; while (index < p2) { if (arr[index] == arr[end]) { index++; } else if (arr[index] < arr[end]) { swap(arr, index++, ++p1); } else { swap(arr, index, --p2); } } swap(arr, p2, end); return new int[]{p1 + 1, p2}; } public void swap(int[] arr, int x, int y) { int tmp = arr[x]; arr[x] = arr[y]; arr[y] = tmp; }