/**
* <b>快速排序</b><br>
* <br>
*
* 基本思想:选择一个基准元素,通常选择第一个元素或者最后一个元素,通过一趟扫描,
* 将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其 排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
*
*
*/
public class QuickSort {
public static int[] sort(int[] array) {
if (array.length > 0) { // 查看数组是否为空
quickSort(array, 0, array.length - 1);
}
return array;
}
public static void quickSort(int[] list, int low, int high) {
if (low < high) {
int middle = getMiddle(list, low, high); // 将list 数组进行一分为二
quickSort(list, low, middle - 1); // 对低字表进行递归排序
quickSort(list, middle + 1, high); // 对高字表进行递归排序
}
}
public static int getMiddle(int[] list, int low, int high) {
int tmp = list[low]; // 数组的第一个作为中轴
while (low < high) {
while (low < high && list[high] >= tmp)
high--;
list[low] = list[high]; // 比中轴小的记录移到低端
while (low < high && list[low] <= tmp)
low++;
list[high] = list[low]; // 比中轴大的记录移到高端
}
list[low] = tmp; // 中轴记录到尾
return low; // 返回中轴的位置
}
}
首先取一个标记位缓存,用于后续其他位置判断大小之用,一般默认都是取第一个值作为标记。
用两个指针分别标记首尾数据
比较尾指针数据和标记位大小,若比标记位小则将首尾指针数据交换,以达到将比标记位大的值都移动到标记位右侧的目地,若比标记位大则无需移动,则将指针一直左移直到首尾指针相遇或者找到一个比标记位小的值。
比较首指针数据和标记位大小,若比标记位大则将首尾指针数据交换,将较大值放在标记位右侧,若比标记位小则将首指针不断右移知道首尾指针相遇或者找到一个比标记位大的值。
循环第3步和第4步,直到首尾指针相遇,当指针相遇意味着整个集合的数据,都根据与标记位比较是大还是小的原则分成左右两个集合,将缓存的标记位数据放到指针指向的位置作为中轴。
将左右两个集合继续重复1-5步骤,直到整个集合排序完毕形成有序序列。
选标记时一般选取首指针标记的数据仅仅是为了整个算法有一个通用标准,你也可以规定固定用最后的值作为标记,不推荐用中间的值,存在较多的复杂性。
标记位数据要缓存,因为尾指针第一次移动如果找到数据了会马上填充在原来标记位的数据上,接下去继续找较大的值填充在第一次移动的值的位置上,这样依次进行可以将较大的值跟较小的值不断交换位置,指针相遇意味着后面的指针访问到了前一个指针已经交换过数据的位置,那么这个位置的数据肯定已经被移动到合适的位置了,所以可以直接将缓存的标记位数据填充在这个位置。