算法与数据结构2-排序算法

选择排序

过程:

arr[0~N-1]范围上,找到最小值所在的位置,然后把最小值交换到0位置。
arr[1~N-1]范围上,找到最小值所在的位置,然后把最小值交换到1位置。
arr[2~N-1]范围上,找到最小值所在的位置,然后把最小值交换到2位置。

arr[N-1~N-1]范围上,找到最小值位置,然后把最小值交换到N-1位置。

估算:

很明显,如果arr长度为N,每一步常数操作的数量,如等差数列一般
所以,总的常数操作数量 = a(N^2) + bN + c (a、b、c都是常数)

所以选择排序的时间复杂度为O(N^2)。

public static void selectionSort(int[] arr) {
 if (arr == null || arr.length < 2) {
 return;
 }
 // 0 ~ N-1
 // 1~n-1 // 2 for (int i = 0; i < arr.length - 1; i++) { // i ~ N-1
 // 最小值在哪个位置上 i~n-1
 int minIndex = i;
 for (int j = i + 1; j < arr.length; j++) { // i ~ N-1 上找最小值的下标 
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
 }
 swap(arr, i, minIndex);
 }
}
public static void swap(int[] arr, int i, int j) {
 int tmp = arr[i];
 arr[i] = arr[j];
 arr[j] = tmp;
}

冒泡排序

过程:

在arr[0~N-1]范围上:
arr[0]和arr[1],谁大谁来到1位置;arr[1]和arr[2],谁大谁来到2位置…arr[N-2]和arr[N-1],谁大谁来到N-1位置

在arr[0~N-2]范围上,重复上面的过程,但最后一步是arr[N-3]和arr[N-2],谁大谁来到N-2位置
在arr[0~N-3]范围上,重复上面的过程,但最后一步是arr[N-4]和arr[N-3],谁大谁来到N-3位置

最后在arr[0~1]范围上,重复上面的过程,但最后一步是arr[0]和arr[1],谁大谁来到1位置

估算:

很明显,如果arr长度为N,每一步常数操作的数量,依然如等差数列一般
所以,总的常数操作数量 = a(N^2) + bN + c (a、b、c都是常数)

所以冒泡排序的时间复杂度为O(N^2)。

public static void bubbleSort(int[] arr) {
 if (arr == null || arr.length < 2) {
 return;
 }
 // 0 ~ N-1
 // 0 ~ N-2 // 0 ~ N-3 for (int e = arr.length - 1; e > 0; e--) { // 0 ~ e
 for (int i = 0; i < e; i++) {
 if (arr[i] > arr[i + 1]) {
 swap(arr, i, i + 1);
 }
 } }}
// 交换arr的i和j位置上的值
public static void swap(int[] arr, int i, int j) {
 arr[i] = arr[i] ^ arr[j];
 arr[j] = arr[i] ^ arr[j];
 arr[i] = arr[i] ^ arr[j];
}

插入排序

过程

很明显,在最差情况下,如果arr长度为N,插入排序的每一步常数操作的数量,还是如等差数列一般

估算

所以,总的常数操作数量 = a(N^2) + bN + c (a、b、c都是常数)
所以插入排序排序的时间复杂度为O(N^2)。

public static void insertionSort(int[] arr) {
 if (arr == null || arr.length < 2) {
 return;
 }
 // 0~0 有序的
 // 0~i 想有序
 for (int i = 1; i < arr.length; i++) { // 0 ~ i 做到有序
 for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
 swap(arr, j, j + 1);
 }
 }}
// i和j是一个位置的话,会出错
public static void swap(int[] arr, int i, int j) {
 arr[i] = arr[i] ^ arr[j];
 arr[j] = arr[i] ^ arr[j];
 arr[i] = arr[i] ^ arr[j];
}

二分法

  1. 在一个有序数组中,找某个数是否存在
  2. 在一个有序数组中,找>=某个数最左侧的位置
  3. 在一个有序数组中,找<=某个数最右侧的位置
  4. 局部最值问题 (不一定有序)
  5. 主要找到一个排他性的标准
public static boolean exist(int[] sortedArr, int num) {
 if (sortedArr == null || sortedArr.length == 0) {
 return false;
 }
 int L = 0;
 int R = sortedArr.length - 1;
 int mid = 0;
 // L..R
 while (L < R) {
 // mid = (L+R) / 2;
 // L 10亿 R 18亿
 // mid = L + (R - L) / 2
 // N / 2    N >> 1 mid = L + ((R - L) >> 1); // mid = (L + R) / 2
 if (sortedArr[mid] == num) {
 return true;
 } else if (sortedArr[mid] > num) {
 R = mid - 1;
 } else {
 L = mid + 1;
 }
 } return sortedArr[L] == num;
}

你可能感兴趣的:(算法-数据结构,排序)