排序
选择排序
- 时间复杂度(O(N^2))
在 N个数中 遍历N-1次 找到最小的数字和第一个数字交换
在便利N-2个中找到最小的数字和第二个数字交换
循环往复 直到N个数遍历完成
package algorithm;import java.util.Arrays;public class selectSort {// 选择排序 第i个位置存放第i位序列public static int tempSize = 20; // 测试多少组数据的长度public static int tempValue = 30; // 数据的值在哪个范围public static int tempTime = 100; // 比较多少组数据public static void selectSort(int[] arr) {if (arr == null) {return;}for (int i = 0; i < arr.length; i++) { // 循环次数int minValue = i; // 比较值for (int j = i + 1; j < arr.length; j++) {if (arr[minValue] > arr[j]) {minValue = j;}}swap(arr, i, minValue);}}public static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void sort(int[] arr) {Arrays.sort(arr);}public static boolean isEqual(int[] arr, int[] arr2) {if ((arr == null && arr2 != null) || (arr != null && arr2 == null)) {return false;}if (arr == null) {return true;}if (arr.length != arr2.length) {return false;}for (int i = 0; i < arr.length; i++) {if (arr[i] != arr2[i]) {return false;}}return true;}public static int[] generator(int size, int value) {int[] arr = new int[(int) ((Math.random() + 1) * size)];for (int i = 0; i < size; i++) {// [-value,value]arr[i] = ((int) (Math.random() * (value + 1)) - (int) (Math.random() * value));}return arr;}// 拷贝数组public static int[] copyArray(int[] array) {// 引用数据类型 都可以为nullif (array == null) {return null;}int[] tempArray = new int[array.length];for (int i = 0; i < array.length; i++) {tempArray[i] = array[i];}return tempArray;}public static void printf(int[] a, int[] b, int[] c) {for (int i = 0; i < a.length; i++) {System.out.println("排序值,sort值,初始值");System.out.printf("%d,%d,%d", a[i], b[i], c[i]);System.out.println();}}public static void main(String[] args) {for (int i = 0; i < tempTime; i++) {int[] arr = generator(tempSize, tempValue);int[] arr1 = copyArray(arr);int[] arr2 = copyArray(arr);selectSort(arr1);sort(arr2);if (!isEqual(arr1, arr2)) {printf(arr1, arr2, arr);return;}}System.out.println("ok");}}
冒泡排序
- 时间复杂度O(N^2)
比较两个相邻的数字的结果 判断是否要交换顺序 (一轮下来的时间复杂度是O(N))
以此重复 知道所有排序完成
package algorithm;import java.util.Arrays;public class bubblingSort {// 冒泡排序public static int tempSize = 20; // 测试多少组数据的长度public static int tempValue = 10; // 数据的值在哪个范围public static int tempTime = 50; // 比较多少组数据// 比较两个相邻的元素,将值大的元素交换到右边// 时间复杂度O(n^2)public static void bubblingSort(int[] arr) {if (arr == null || arr.length < 2) { // 注意边界问题return;}for (int i = 0; i < arr.length - 1; i++) { // 循环次数// 每次循环都会确定i+1个排序 所以要 arr.length - (i + 1)// 注意这里的arr.length - i -1for (int j = 0; j < arr.length - i - 1; j++) {// 这里的if (arr[j] > arr[j + 1]) {swap(arr, j, j + 1);}}}}public static void sort(int[] arr) {Arrays.sort(arr);}// 交换顺序public static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}// 生成随机数组public static int[] generateRandomArray(int size, int value) {// 生成size长度的数组 并且值在 [0-value - 1] 之间int[] array = new int[(int) ((Math.random() + 1) * size)];for (int i = 0; i < array.length; i++) {array[i] = (int) (Math.random() * value);}return array;}// 拷贝数组public static int[] copyArray(int[] array) {// 引用数据类型 都可以为nullif (array == null) {return null;}int[] tempArray = new int[array.length];for (int i = 0; i < array.length; i++) {tempArray[i] = array[i];}return tempArray;}public static boolean isEqual(int[] arr, int[] rightArray) {if (arr == null && rightArray != null || arr != null && rightArray == null) {return false;}if (arr == null) {return true;}if (arr.length != rightArray.length) {return false;}for (int i = 0; i < arr.length; i++) {if (arr[i] != rightArray[i]) {return false;}}return true;}public static void printf(int[] a, int[] b, int[] c) {for (int i = 0; i < a.length; i++) {System.out.println("排序值,sort值,初始值");System.out.printf("%d,%d,%d", a[i], b[i], c[i]);System.out.println();}}public static void main(String[] args) {for (int i = 0; i < tempTime; i++) {int[] arr = generateRandomArray(tempSize, tempValue); // 第一组数据int[] rightArray = copyArray(arr); // 拷贝一组数组 用于比较int[] tempArray = copyArray(arr); // 拷贝一组数组 用于比较bubblingSort(arr);sort(rightArray);// 比较是否两个相等if (!isEqual(arr, rightArray)) {printf(arr, rightArray, tempArray);return;}}System.out.println("ok");}}
插入排序
时间复杂度O(N^2)
将第i位的元素插入到前0- (i-1) 中去 ```java package algorithm;
import java.util.Arrays;
public class insertSort { // 插入排序 i>=1 从小到大 // 将第i位的元素插入到前0- (i-1) 中去 public static int tempSize = 20; // 测试多少组数据的长度 public static int tempValue = 100; // 数据的值在哪个范围 public static int tempTime = 1000; // 比较多少组数据
// 时间复杂度O(n^2)public static void insertSort(int[] arr) {if (arr == null || arr.length < 2) { // 注意边界问题return;}for (int i = 1; i < arr.length; i++) {for (int j = 0; j < i; j++) {if (arr[j] > arr[i]) {// 往后移动一位move(arr, j, i);}}}}public static void sort(int[] arr) {Arrays.sort(arr);}// 插入 往后位移 从i到j位往后移public static void move(int[] arr, int i, int j) {// 数据移动是从 [i,j)int tampValue = arr[j];for (int k = j - 1; k >= i; k--) {arr[k + 1] = arr[k];}arr[i] = tampValue;}// 生成随机数组public static int[] generateRandomArray(int size, int value) {// 生成size长度的数组 并且值在 [0-value - 1] 之间int[] array = new int[(int) ((Math.random() + 1) * size)];for (int i = 0; i < array.length; i++) {array[i] = (int) (Math.random() * value);}return array;}// 拷贝数组public static int[] copyArray(int[] array) {// 引用数据类型 都可以为nullif (array == null) {return null;}int[] tempArray = new int[array.length];for (int i = 0; i < array.length; i++) {tempArray[i] = array[i];}return tempArray;}public static boolean isEqual(int[] arr, int[] rightArray) {if (arr == null && rightArray != null || arr != null && rightArray == null) {return false;}if (arr == null) {return true;}if (arr.length != rightArray.length) {return false;}for (int i = 0; i < arr.length; i++) {if (arr[i] != rightArray[i]) {return false;}}return true;}public static void printf(int[] a, int[] b, int[] c) {for (int i = 0; i < a.length; i++) {System.out.println("排序值,sort值,初始值");System.out.printf("%d,%d,%d", a[i], b[i], c[i]);System.out.println();}}public static void main(String[] args) {for (int i = 0; i < tempTime; i++) {int[] arr = generateRandomArray(tempSize, tempValue); // 第一组数据int[] rightArray = copyArray(arr); // 拷贝一组数组 用于比较int[] tempArray = copyArray(arr); // 拷贝一组数组 用于比较insertSort(arr);sort(rightArray);// 比较是否两个相等if (!isEqual(arr, rightArray)) {printf(arr, rightArray, tempArray);return;}}System.out.println("ok");}
}
<a name="W5egR"></a>
# 快速排序
```java
import java.util.Arrays;
public class quickSort {
/**
* 快速排序
* 时间复杂度nlogn
* @param arr
* @desc 选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;
* 其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,
* 整个排序过程可以递归进行,以此达到整个数据变成有序序列。
*/
public static void quickSort(int[] arr) {
if(arr == null || arr.length < 2) return;
int pre = 0; //左边界
int next = arr.length -1; //右边界
quickSortStack(arr,pre,next);
}
public static void quickSortStack(int[] arr,int i, int j) {
if(i >= j) return;
int current = arr[i]; //基准值
// 保存边界值
int pre = i;
int next = j;
while(pre < next) {
// 如果 next的值比当前的值大 则继续往下查找
while(pre < next && arr[next] >= current) {
next--;
}
// 这里会走 arr[next] < current 交换顺序
if(pre < next) {
arr[pre] = arr[next];
//之后往pre向上走判断
pre++;
// 之后next这个数字就是基准值下标了
}
// pre的值比当前基准值小
while(pre < next && arr[pre] <= current) {
pre++;
}
// arr[pre] > current
if(pre < next) {
arr[next] = arr[pre];
next--;
// 之后pre这个数字就是基准值下标了
}
}
// 结束后 pre = next 基准值放于中间
arr[pre] = current;
quickSortStack(arr,i,pre-1);
quickSortStack(arr,pre+1,j);
}
public static void sort (int[] arr) {
Arrays.sort(arr);
}
public static void swapArray(int[] arr,int a,int b) {
if(a == b) return;
arr[a] = arr[a] ^ arr[b];
arr[b] = arr[a] ^ arr[b];
arr[a] = arr[a] ^ arr[b];
}
public static boolean isEqual(int[] arr, int[] sort) {
if((arr == null && sort !=null) || (arr != null && sort == null)) {
return false;
}
if(sort == null) {
return true;
}
if(arr.length != sort.length) {
return false;
}
for (int i = 0; i < arr.length; i++) {
if(arr[i] != sort[i]) {
return false;
}
}
return true;
}
public static int[] tempNumber(int size,int result) {
int[] arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = ((int)((Math.random() *result) + 1) - (int)(Math.random() * result));
}
return arr;
}
public static int[] copyArr(int[] arr) {
int[] copyArr = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
copyArr[i] = arr[i];
}
return copyArr;
}
public static void systemOut(int[] arr, int[] sortArr, int[] tempArr) {
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr:%d,sortArr:%d,tempArr:%d",arr[i],sortArr[i],tempArr[i]);
System.out.println();
}
}
public static void main(String[] args) {
int tempSize = 2; //比较次数
int size = 10;// 数组长度
int result = 50;
for (int i = 0; i < tempSize; i++) {
int[] resultArr = tempNumber(size,result);
int[] sortArr = copyArr(resultArr);
int[] tempArr = copyArr(resultArr);
quickSort(resultArr);
sort(sortArr);
if(!isEqual(resultArr,sortArr)) {
systemOut(resultArr,sortArr, tempArr);
return;
}
}
System.out.println("ok");
}
}
二分法
时间复杂度: log2^N (二分不一定要有序)
- 一个有序数组 查找某个数是否存在
- 一个有序数组 找>=某个数的最左侧的位置
- 一个有序数组 找<=某个数的最右侧位置
- 局部最小值问题(数组可以无序 但是相邻位置的数组不能相等)
// 二分法 谨记二分法不一定要有序 public static int dichotomy(int[] arr, int result) { int flag = -1; if (arr == null) { return flag; } int pre = 0; int next = arr.length - 1; while (pre < next) { int middle = (int) ((pre + next) / 2); // 这里的middle 可以优化 pre + next 可能会有长度溢出的风险 // int middle = (int) pre +((next - pre) >> 1) if (arr[middle] > result) { next = middle - 1; } if (arr[middle] < result) { pre = middle + 1; } if (arr[middle] == result) { flag = middle; break; } } return flag; }
