快速排序是冒泡的一种增强,冒泡的时间复杂度是O(n^2),我们首先看一下冒泡的代码:public class Demo1 { /** * 进行冒泡排序 * 1.其实就是通过相邻两个数进行一个比较,比较出最大或者最小的数值 * 2.8 ---> 7 ---> 6 * */ public void sortingMp(int[] arr){ int value = 0; //循环完毕最大的数值在最后arr.length-1的位置 for(int a=0;a<arr.length;a++){ if(arr[a] > arr[a+1]){ value = arr[a]; arr[a] = arr[a+1]; arr[a+1] = value; } } //第二次循环只要是找到倒数第二大的数 放置arr.length-1-1的位置 for(int a=0;a<arr.length-1;a++){ if(arr[a] > arr[a+1]){ value = arr[a]; arr[a] = arr[a+1]; arr[a+1] = value; } } //以此类推我们会发现最后a < arr.length-1-1-? == arr.length-(arr.length-1) //arr.length-1就是我们需要循环上述代码的次数 } /** * 这个方法是将上述方法进行改良整合 * */ public void sortingMpG(int[] arr){ int value = 0; for(int b=0;b<arr.length;b++){ for(int a=0;a<arr.length-1-b;a++){ if(arr[a] < arr[a+1]){ value = arr[a]; arr[a] = arr[a+1]; arr[a+1] = value; } } } System.out.println(Arrays.toString(arr)); }
注意:sortingMpG方法是冒泡一般使用的方法,sorting方法是冒泡的一种推演形式.1 通过推演很好的知道,我们这里是通过从小 ---> 大的排序,每一次内部的for进行的是最大值(如果是大--->小那么就是最小值)的寻找定位 1.1 所做的逻辑就是:1.相邻比较 2.最大的值进行交换 ---> 数组尾部进行最大值交换2 冒泡排序的优点是比较简单好理解,坏处就是不管是有序还是无序的情况都需要进行n^2比较,如果是无序的话情况会更糟糕。根据对冒泡排序的缺点,快速排序可以说是对冒泡的一次优化排序1 快速排序的思想是通过一个基准数将数据进行拆分 ------> left <= 基准数 <= right 左边小于基准数,右边大于基准数 1.1 第一次的拆分之后我们可以对left 和 right的两段数据进行如上操作,这里就很好的猜想到是使用递归的方式(我们不清楚能循环多少次)那么时间复杂度可以看到left 和 right两个数组全部走一遍是算一次n,最坏的情况是有序数组进行排序 例:如果使用最右边的9作为基准数 1 2 3 4 5 6 7 8 9 ---> left:1 2 3 4 5 6 7 8 rightL:9 ---> 1 2 3 4 5 6 7 8 ---> left:1 2 3 4 5 6 7 rightL:8 ... 其实可以看到最慢的情况和冒泡是一个样子的都是O(n^2),同时我们可以看到最快的情况O(nlog^n)快排代码:
/** * 快速排序 * 其实和希尔排序用到了一种思想分成不同段进行排序 * */public class Demo6Fast { /** * 快速排序第一版本1.0 * */ public void fast(int[] arr,int left,int right){ int i = left; int j = right; int value = 0; if(i >= j){ return; } int key = arr[left]; //基准数我们选取最左边的,当然也可以选择中间的数 while(i < j ) { while(arr[j] >= key && i < j){ //从右边进行比较,如果有比基准数小的那么就和基准数互换位置 j--; } if(i <j) { value = arr[i]; arr[i] = arr[j]; arr[j] = value; } while(arr[i] <= key && i < j){ //从左边进行比较,如果有比基准数大的那么就和基准数互换位置 i++; } if(i <j) { value = arr[i]; arr[i] = arr[j]; arr[j] = value; } } fast(arr,left,i-1); fast(arr,j+1,right); } /** * 快速排序第二版 2.0 * 快速算法 / 双轴快排 * key的取值如果使用 i+r / ? 这种方式 ?== 2 的取值必定是 i < ? < r * 但是 i + r / 3 4等等的话可能需要的基准数就不再i - r之间了,所以一般我们取中间的数或者l;r两端 * 如果不放心这是一个有序数列的话就取中间最保险。 * */ public int fast_2(final int[] arr,int left,int right){ int l = left; int r = right; int value = 0; if(l >= r){ return -1; } int key = arr[(l+r)/2]; //控制不停的交换 while(l < r){ while(arr[r] > key && l < r){ r--; } while(arr[l] < key && l < r){ l++; } //进行交换 value = arr[l]; arr[l] = arr[r]; arr[r] = value; /** * 这里出现了死循环,一直不知道为什么 * 通过debug发现我使用了left++,right++ * 这里应该是用的是定义的新的左右局部变量进行++操作 * */ if(arr[r] == key && l < r ){// left++; l++; } if(arr[l] == key&& l < r ){// right--; r--; } } return l; } public void fast_3(final int[] arr,int left,int right){ int min = fast_2(arr,left,right); if(min == -1){ return; } fast_3(arr,min+1,right); fast_3(arr,left,min-1); }以上代码第一种方式看起来会比较简单,不停的进行左右的筛选比较,左或者右出现大或者小的情况就进行替换操作第二种方式其实很类似,实现其实道理是一致的,只是看起来抽象了一点(逻辑是一致的,只是对第一种进行了简单整理)
后续会对所有的排序算法进行相关的操作,如有问题欢迎留言询问~