快速排序
通过一轮的排序将序列分割成独立的两部分,其中一部分序列的关键字(这里主要用值来表示)均比另一部分关键字小。继续对长度较短的序列进行同样的分割,最后到达整体有序。在排序过程中,由于已经分开的两部分的元素不需要进行比较,故减少了比较次数,降低了排序时间。
详细描述
首先在要排序的序列 a 中选取一个中轴值,而后将序列分成两个部分,其中左边的部分 b 中的元素均小于或者等于 中轴值,右边的部分 c 的元素 均大于或者等于中轴值,而后通过递归调用快速排序的过程分别对两个部分进行排序,最后将两部分产生的结果合并即可得到最后的排序序列。
为了实现一次划分,我们可以从数组(假定数据是存在数组中)的两端移动下标,必要时交换记录,直到数组两端的下标相遇为止。为此,我们附设两个指针(下角标)i 和 j, 通过 j 从当前序列的有段向左扫描,越过不小于基准值的记录。当遇到小于基准值的记录时,扫描停止。通过 i 从当前序列的左端向右扫描,越过小于基准值的记录。当遇到不小于基准值的记录时,扫描停止。交换两个方向扫描停止的记录 a[j] 与 a[i]。 然后,继续扫描,直至 i 与 j 相遇为止。扫描和交换的过程结束。这是 i 左边的记录的关键字值都小于基准值,右边的记录的关键字值都不小于基准值。
通过两个不相邻元素交换,可以一次交换消除多个逆序,加快排序速度。快速排序方法在要排序的数据已经有序的情况下最不利于发挥其长处。
快速排序示例代码
/**
* 快速排序
*
* @author bianjie
*
*/
public class QuickSort {
/**
* 进行快速排序
* @param data 要排序的数据
* @param left 左侧起始位置
* @param right 右侧起始位置
*/
public static void quickSort(int data[], int left, int right) {
int i = left;
int j = right;
//获取基准值
int temp = data[left];
if (left >= right)
return;
while (i != j) {
//右侧的值比基准值大,右侧下标前移
while (i < j && data[j] >= temp)
j--;
//此时右侧值小于基准值
if (i < j)
// a[i]已经赋值给temp,所以直接将a[j]赋值给a[i],赋值完之后a[j],有空位
data[i] = data[j];
//左侧的值比基准值小,左侧下标后移
while (i < j && data[i] <= temp)
i++;
//此时左侧值大于基准值
if (i < j)
data[j] = data[i];
}
// 把基准插入,此时i与j已经相等
data[i] = temp;
printData(data);
//递归左边
quickSort(data, left, i - 1);
//递归右边
quickSort(data, i + 1, right);
}
/**
* 打印数据
*
* @param data
*/
public static void printData(int data[]) {
for (int i : data) {
System.out.print(i + " ");
}
System.out.println();
}
public static void main(String[] args) {
int data[] = { 23, 10, 5, 22, 12, 33 };
QuickSort.printData(data);
// 进行排序
QuickSort.quickSort(data,0,data.length-1);
}
}
运行结果