快速排序
定义:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
思路:先找出一个数(一般都是第一个数,即arr[0]),从这个数开始(即key = arr[0]),先从该数组的最右边开始找,直到找到第一个比该数小的数(假设找到的下标为j),此时,将这个数赋值给第一个数(arr[0] = arr[j]),然后从该数组的最左边开始找,直到找到第一个比这个数大的数(假设下标为i),此时,将这个数赋值为arr[j],然后重新从最右边开始找与key对比,交换,从最左边开始,交换,一个这样循环下去,最后数组就会被划分成在数key的左边的数,都比key小,在key右边的数,都比key大,这样第一轮划分结束,然后将key左右两边的树,各自再结果上述的划分,最终数组即会是从小到大的排序;
由上图我们可以看出在第一轮划分的过程,这样 就分出了左右个一块,且左边比49小,右边比49大(或者等于,图中的 * 用与区别两个一样的数,可用于检验该算法是否稳定,即排完序后,相同用的数如果前后顺序未变,则稳定),第一次划分后,将左右接着划分,直到结束,这样,数组就排序完毕
性能分析
时间复杂度为O(N*logN),且该排序方式是不稳定的(虽然在上诉看起来是稳定的,这里我的例子举的不好,如果在第一个49和14之间再加一个49,排序后就能发现,位置先后发生了变化)
代码:
package Test;
public class Test {
public static void main(String[] args) {
int[] arr = {49,14,38,74,96,65,8,49,55,27};
quickSort(arr,0,arr.length - 1);
for(int i = 0;i < arr.length;i++)
{
System.out.print(arr[i] + "\t");
}
}
public static void quickSort(int[] arr,int low,int high)
{
if(low >= high)
return;
int i = low; //当前数组块的最小下标
int j = high; //当前数组块的最大下标
int key = arr[low]; //本次交换时用来对比的数
while(i < j) //i >= j时,说明本轮对数组的划分结束
{
while(i < j && arr[j] >= key) //从最右边开始找,直到找到比key大或者相等的数为止
{
j--; //最后一个不是要找的,所以向前推一个,直到和i相等或者小于i
}
arr[i] = arr[j]; //已经找到时,将arr[i] = arr[j],即使没找到,由于一直的j--,此时的i == j;
while(i < j && arr[i] <= key) //从最左边开始找,直到找到比key小或者相等的数为止
{
i++; //第一个不是要找的,所以向后推一个,直到和j相等或者大于i
}
arr[j] = arr[i]; //已经找到时,将arr[j] = arr[i],即使没找到,由于一直的i++,此时的j == i;
}
arr[i] = key; //这一轮的排序结束,此时的arr[i] = key;且在i之前的数,都会小于key,在i之后的数,都会大于key
/******第一轮划分结束******/
//此时的数组已经被分为三块了,一个是分界线arr[i] = key;一个是i之前的一串数组(未排序),一个是i之后的一串数组(未排序),
quickSort(arr,low,i - 1); //将i之前的重新放入该方法排序
quickSort(arr,i + 1,high); //将i之后的重新放入该方法排序
}
}
截图: