快速排序法,一听名字就觉得这个排序方法效率很高。那么究竟什么是快速排序法呢?举个例子,现在有一个未排序的数组【5,12,3,1,7,8,4】
,我们从中选择一个基准数
,也可以理解为用来参照的数。
在这里我们可以将 i 和 j 想象为两个哨兵,确定了 i 和 j 的位置之后,
首先哨兵j往左边搜索,当它找到小于
基准数的时候就停下来,
正好 j 所在的位置的数就比基准数 5 要小,那么 j 就不继续往左搜索了。
这个时候哨兵j就会告诉哨兵i:“嘿我找到了,该你了!”。
哨兵i听到后就开始行动,从左往右开始搜索,它的目标是寻找大于
基准数的值。
然后i在索引为 2 的位置停了下来,这里的值是 12,
i 停下来后也告诉 j:“我也找到啦!”。
接下来哨兵 i 和哨兵 j 就会交换手中的目标,也就是12与4的位置进行交换。
完成交换后,哨兵 j 继续搜索它的目标,然后它找到了1。接下来轮到 i 开始搜索,可是 i 走着走着,就跟 j 碰在一起
了。
这下可不好了,j在1那里停下来了,i也在1那里停下来了,他们互不相让,就快要打起来了。在经过一番谈论后,它们决定将责任推给1,j不要了,i也不要了,并且把象征着它们友谊的基准数5拿过来,和1交换。这样哨兵i和哨兵j就愉快的完成了这次搜索任务。
这个时候的数组为,排序还没有完成,但是我们可以发现,
在基准数5的左边,都是比它小的数,右边都是比他大的数。
然后再分别对左右两边的数进行快速排序。
排序的最终结果就是这样了
接下来要思考的就是,如何将快速排序用代码表示出来。先来看看我们需要的参数,首先是要进行排序操作的数组arr
,然后就是基准数temp
,最后还有两个哨兵 i 和 j
。这里我以Java代码为例
public static void qsort(int arr[],int start,int end) {
int i = start; //声明i用来接收start的值
int j = end; //声明j用来接收end的值
int x,y; //x和y用来存储arr[i]和arr[j]对应的值
if(i>j){
//如果i>j了,说明哨兵i和哨兵j已经碰头,就跳出循环
//作为递归的结束条件
return;
}
// temp 用于存放基准数
int temp = arr[start];
在这里声明了哨兵 i 和哨兵 j ,他们的值就是数组的开始索引和结束索引。而后声明了 x 和 y,用来存放哨兵i和哨兵j搜索到的目标值。以 i > j 作为递归的结束条件。接下来就让两个哨兵开始搜索目标
while(i<j){
//哨兵j的目标是大于基准数的值
//如果j所在位置的值小于基准数,则j--,继续往左搜索
while(temp<=arr[j]&&i<j){
j--;
}
//同理,哨兵i的目标是小于基准数的值
//如果j所在位置的值大于基准数,则i++,继续往右搜索
while(temp>=arr[i]&&i<j){
i++;
}
if(i<j){
//当i和j都找到目标时,进行交换
x=arr[i];
y=arr[j];
arr[i]=y;
arr[j]=x;
}
}
这个时候循环结束,最后我们就需要将i和j共同占有的位置上的值与基准数进行交换
arr[start]=arr[i];
//或者是 arr[start]=arr[j];
arr[i]=temp;
我们得到了第一次排序的结果,接下来就是调用递归再次循环,但是传递的参数发生了改变
//将基准数的左边进行快速排序
qsort(arr,start,j-1);
//将基准数的右边进行快速排序
qsort(arr, j+1, end);
}
在main方法中调用我们写好的方法,测试一下
public static void main(String[] args) {
int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
qsort(arr, 0, arr.length-1);//调用递归
for (int i = 0; i < arr.length; i++) {
//循环输出
System.out.print(arr[i]+" ");
}
}
输出结果为
快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准数,将小于基准数的放在左边,大于基准数的放在右边。这样每次循环就确定了一半的数,而不是像冒泡排序法那样只能在相邻的数之间两两相比
。总的比较和交换次数就少了,速度自然就快了。
推荐参考 https://blog.csdn.net/u014241071/article/details/81565148
写的很好,图文并茂