快速排序算法是对冒泡排序算法的一种改进。
它的基本思想就是:首先,在需要排序的序列中选取一个基准数,通过基准数将需要排序的数组分割成两个独立的部分,这两部分数据要满足其中的一部分数据中的所有数据要比另一部分的数据都要小,然后再按照这个方法对这两部分数据进行不断的分割,直到不能分割为止,整个过程可以通过递归的进行,以此达到整个数据达到有序序列。
说白了,就是给基准数找到正确的索引位置的过程。
如图表示,我们假设选取的这个基准数为数组的第一个数据,然后声明一个临时变量来存储这个基准数据(tmp = 34),分别设置两个指示标志,head指向起始位置,tail指向尾部,方便从前后两端对数组进行扫描。
首先,从数组的尾部向前进行扫描,如果扫描扫到的数据比基准数要大,就将tail减一,指向上一个数据,如图所示:
如果发现元素比该基准数要小的时候(12<=tmp),就tail处的值赋值到head处,如图所示:
然后,开始从前往后进行扫描,如果扫描的数据比基准数要小的话,就让head加一,若扫描的数据要比基准数要大话(56>=head)就将扫描到的值赋值给tail位置上,结果如下:
然后再从后往前扫描,原理同上,当发现扫描的值<=tmp的时候将扫描的值赋值给head,不断重复上面的流程直到head==tail时,结束循环,如图所示:
现在tail与head指示的位置就是基准值(tmp)所在的正确位置,将tmp赋值到这个位置,如图所示:
从上面实例可以看出,所谓的快速排序就是将数组中所有大于基数(tmp=34)的排到基准位的右侧,将所有大于基准的排到左侧,然后再将数组基于基准数分为两个数组,通过递归的方式重复上面的步骤就能正确排序的数组。
实例代码:
public class PracticeTest { public static void main(String[] args) { int[] arr = { 29, 78, 15, 107, 23, 22, 76, 1, 5, -8, 2, 0, -1, 24 }; System.out.println("排序前:"); System.out.println(Arrays.toString(arr)); quickSort(arr, 0, arr.length-1); System.out.println("排序后:"); System.out.println(Arrays.toString(arr)); } private static void quickSort(int[] arr, int head, int tail){ if(head < tail){ //递归出口条件 int index = getIndex(arr,head,tail);//获取基准数排序后位置 quickSort(arr,head,index-1);//对基准数左侧的数据再排序 quickSort(arr,index+1,tail);//对基准数据右侧的再排序 } } private static int getIndex(int[] arr, int head, int tail){ int tmp = arr[head];//获取基准值 while(head < tail){//不断的按照先从尾向前,再从前向后不断查询过程,直到head==yail的时候 while (head < tail && arr[tail] >= tmp){//从尾部向前查询大于等于基准值 tail--; } //如果队尾元素小于tmp了,需要将其赋值给head arr[head] = arr[tail]; while(head < tail && arr[head] <= tmp){ head++; } //当队首元素大于tmp时,需要将其赋值给head arr[tail] = arr[head]; } //当head == tail的时候,此时head和tail的位置就是tmp正确的位置 arr[head] = tmp; return tail;//返回正确的基数位置 } }
总结:
1>从数组中获取一个基数(tmp);
2>设置前后标志(head和tail);
3>先从后往前查询>=tmp的数据,然后赋值给head处,然后再从前往后查询>=tmp的数据,将这个数据赋值给tail处,不断的重复直到head==tail的时候为止,确定tmp的最终为止。
4>快速排序就是一个递归的分割数据,定义基准数据,确定基准数据在数组中的位置的方法。