浅谈快速排序算法
Posted Bossky程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈快速排序算法相关的知识,希望对你有一定的参考价值。
今天有个同学问起一道关于快排的考试题,一时竟没想起来,确实排序算法在日常工作中自己写的机会不多,所以也就遗忘了。
虽然用的机会不多,但是知道总是好的,所以趁着有空,恶补一下。
快速排序是交换排序的一种,是冒泡排序的改进,使用分治法策略来把一个序列(list)分为两个子序列(sub-lists)。
步骤为:
1.从数列中挑出一个元素,称为"基准"(pivot),
2.重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
3.递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
下面我们通过举例说明排序过程
待排元素
{73,13,70,23,95,16,5,68,26,45}
首先,我们要挑出一个元素为"基准",这个"基准"并没有硬性规定,但是为了处理方便,我们一般都选择数组的第一个元素。则对于待排元素
pivot=73
然后,我们拿pivot跟剩下的元素比较,我们先从后向前扫描,找到第一个比pivot小的则(后面的都要比pivot大的),同理,我们从前向后扫描,找到第一个比pivot大的(前面的 都要比pivot小)。
扫描后,我们得到了95跟45这两个数的位置不对。
这时,我们想一想把45跟95交换一下位置,是不是就符合要求了?
交换后,得出
{73,13,70,23,45,16,5,68,26,95}
现在我们从前扫描到了45的位置,确定了45之前的都比privot小,从后扫描到了95的位置,确定95之后都比privot大。
所以我们从这两个点继续扫描(第一次扫描还没结束的),
一样先从后往前,到26时,发现比privot小了。再从45开始从前向后扫描。
当扫描到26时,还是没找到比privot大的数,扫描结束(后面的都比privot大了)
我们得出了26之前的数(包括26)都比privot大小,26之后的数都比privot大(不包括26),这时我们就要考虑privot的位置了。
因为我们选择的是数据第一位做为基准,所以privot也是在26前面的。
并且privot>26,所以交换它们的位置。
最终第一次扫描的结束如下
{26,13,70,23,45,16,5,68,73,95}
这时,我们得出了在基准位置(值73所在)前面的值都小于它,后面的则都大于它。有了这个,我们可以将数列分割成两个子数列
{26,13,70,23,45,16,5,68} ,{73}, {95}
之前的基准不需要在参与排序了。
我们开始第二次扫描,步骤与第一次扫描类似,分别对两个子数列扫描排序。
得出
{16,13,5,23,26,45,70,68},{73}, {95}
第一个子数列最终的基准位置在26,再次分割
第二个子数列{95}只有一个元素,所以是不需要再分隔跟排序的。
第二次扫描的结果为
{16,13,5,23},{26},{45,70,68},{73} , {95}
第三次扫描
{5,13,16,23},{26},{45,70,68} ,{73}, {95}
分割
{5,13},{16},{23},{26},{45,70,68} ,{73}, {95}
第四次扫描
{5,13},{16},{23},{26},{45,70,68} ,{73}, {95}
分割
{5},{13},{16},{23},{26},{45,70,68} ,{73}, {95}
第五次扫描
{5},{13},{16},{23},{26},{45,70,68} ,{73}, {95}
分割
{5},{13},{16},{23},{26},{45},{70,68} ,{73}, {95}
第六次扫描
{5},{13},{16},{23},{26},{45},{68,70} ,{73}, {95}
分割
{5},{13},{16},{23},{26},{45},{68},{70} ,{73}, {95}
将上面的分析转换成代码
public static void quickSort(int[] arr) {
quickSort(arr, 0, arr.length - 1);
}
static void quickSort(int[] arr, int first, int last) {
if (first >= last) {
return;
}
int pivot = arr[first];
int low = first + 1;
int high = last;
while (high != low) {
// 从后向前扫描,保证后面的大于pivot
while (low < high && arr[high] >= (pivot)) {
high--;
}
// 从前向后扫描,保证前面的小于pivot
while (low < high && arr[low] < (pivot)) {
low++;
}
if (high != low) {// 还没相遇
int temp = arr[high];
arr[high] = arr[low];
arr[low] = temp;
}
}
int p = 0;
if (pivot > arr[high]) {
arr[first] = arr[high];
arr[high] = pivot;
p = high;
} else {
p = first;
}
quickSort(arr, first, p - 1);
quickSort(arr, p + 1, last);
}
以上是关于浅谈快速排序算法的主要内容,如果未能解决你的问题,请参考以下文章