排序算法的java实现及复杂度总结1
各种排序算法总结和复杂度总结:
-
冒泡排序
public static void bubbleSort(int[] arr){ //每次都要进行类型判断防止非空操作和无效的比较操作 if (arr == null || arr.length < 2) { return; } for (int i = 0;i < arr.length - 1;i++){ for (int j = 0; j < arr.length - 1 -i ; j++) { if (arr[j] > arr[j+1]){ int t; t=arr[j]; arr[j]=arr[j+1]; arr[j+1]=t; } } } }冒泡排序是每个把最大的值都放在最后面进行排序
时间复杂度O(N^2)
空间复杂度O(1)
-
对数器的概念(这个后面自己在进行总结各种对数器,看老师的给的自己总结下来)
- 想测试的方法A
- 绝对正确但是复杂度高的B
- 产生一个输入的随机样本,短的就行
- 二方法输出结果进行比较
-
选择排序
public static void selectSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 0; i < arr.length - 1; i++) { int min = i; for (int j = i + 1; j < arr.length; j++) { if (arr[min] > arr[j]){ min = j; } } int t; t = arr[i]; arr[i] = arr[min]; arr[min] = t; } }选择排序是选出最小的值然后放在最前面
时间复杂度O(N^2)
空间复杂度O(1)
-
插入排序
public static void insertSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 1; i < arr.length - 1; i++) { for (int j = i+1; j > 0 && arr[j-1] > arr[j]; j--) { int t; t = arr[j]; arr[j] = arr[j-1]; arr[j-1] = t; } } }插入排序就像打牌一样,把新抓进来的数 从尾到头进行插入
-
递归函数的时间复杂度的估算方法
利用到的是master公式
T(N)=a*T(N/b)+O(N^d)
N是原来的样本量
N/b是子过程的样本量
O(N^d)是除了样本量剩下的子过程的大小
例如:
二边递归找最大值
T(N) = 2*T(N/2) + o(1)
结果:
![]()
上面的结果为O(2^log(2,2))
-
归并排序
public static void mergeSort(int[] arr) { if (arr == null || arr.length < 2) { return; } mergeSort(arr, 0, arr.length - 1); } private static void mergeSort(int[] arr, int l, int r) { //递归先找出出口 if (l == r) {//只剩下自己了一定是有序的 return; } int mid = l + ((r - l)>>2);//等同于这个东西(l + r) / 2因为l+r可能会超过正数的范围进行溢出 mergeSort(arr, l, mid); mergeSort(arr, mid + 1, r); merge(arr, l, mid, r); } private static void merge(int[] arr, int l, int mid, int r) { int[] hlep = new int[r - l + 1];//暂存数组 int i = 0;//转移数组 int p1 = l;//左指针标记左边的数组的开头 int p2 = mid + 1;//右指针标记右边的开头 while (p1 <= mid && p2 <= r) {//进行比较归并 hlep[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= mid) {//剩下的加入 hlep[i++] = arr[p1++]; } while (p2 <= r) {//剩下的加入 hlep[i++] = arr[p2++]; } //填回原来的数组中 for (i = 0; i < r - l + 1; i++) { arr[l + i] = hlep[i]; } }把整个序列分成二部分,分成一个的时候就已经是有序序列了,然后在进行合并就可以了
时间复杂度这里就运用到了前面的master公式
T(N)=2T(N/2)+O(N)
a =2 b = 2 d= 1
所以整个的复杂度为
O(N*logN)
空间复杂度O(N)//因为借用到了一个等长的额外变量进行存储中间值,所以空间复杂度是O(N)
-
归并排序解决实际问题-小和问题,逆序对问题
- 小和问题:
public static int mergeSort(int[] arr, int l, int r) { if (l == r) { return 0; } int mid = l + ((r - l) >> 2); return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r); } private static int merge(int[] arr, int l, int mid, int r) { int[] help = new int[r - l + 1]; int result = 0; int i = 0;//标记help的长度 int p1 = l; int p2 = mid + 1; while (p1 <= mid && p2 <= r) { //左右二边都是有序的,如果右边的值大于当前的值,代表从这个数以后的值都大于这个值,而且右边的本来就在左边的右边 result += arr[p1] < arr[p2] ? arr[p1] * (r - p2 + 1) : 0; help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; } while (p1 <= mid){ help[i++] = arr[p1++]; } while ( p2 <= r) { help[i++] = arr[p2++]; } for (int j = 0; j < help.length; j++) { arr[l+j] = help[j]; } return result; }利用归并排序去解决问题,递归时找到递归出口和把大问题化成同样的小问题
-
逆序对问题
只更改while里面的代码既可 while (p1 <= mid && p2 <= r) { //左右二边都是有序的,如果右边的值大于当前的值,代表从这个数以后的值都大于这个值,而且右边的本来就在左边的右边 result += arr[p1] > arr[p2] ? (mid - p1 + 1) : 0; help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++]; }
里面的help数组要改成小于等于 不然会丢失一些数,前面小和是要保证相等的时候,前面的不动,后面的动,不然也会丢失一些数据值的


浙公网安备 33010602011771号