八大排序算法之快速排序(Java实现)

参考书籍:大话数据结构P417

动图:https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html,j控制右往左走,i控制左往右

不要急着写代码,先捋思路,可以先参照代码进行理解

快排基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中基准值的左边都比基准值小,基准值的右边都比基准值大,则分别对这两部分进行递归排序,以达到有序的目的

以从小到大排序为例,首先选左边第一个为基准值(当然你也可以选其他),然后设置两个指针,从右往左找到比基准值小的数然后与基准值交换,相当于比基准值小的换到左边,再从左往右,找到比基准值大的然后与基准值交换,相当于比基准值大的换到右边

过程如图,一遍排序之后,基准值就会到中间,左边均小于基准值,右边则均大于

{20,10,40    ,50,     70,80,60,90}

不过还没排好序,还需要对左右两边进行递归排序,不断重复此过程,r表示右“指针”,L表示左“指针”

八大排序算法之快速排序(Java实现)_第1张图片

代码实现如下:

package Sort;

import java.util.Arrays;

public class QuickSort {
	public static void main(String[] args) {
		int[] arr = {50,10,90,70,40,80,60,20};
		quickSort(arr, 0, arr.length-1);
	}
public  static void quickSort(int[] arr,int left,int right){
	int pivot=0;//基准值的索引
	if(left=pivotkey)
		{
			right--;
		}
		//比基准值小的数与基准值交换,即放在基准值的左边
		swap(arr,left,right);
		//找到比基准值大的
		while(left

为什么外面已经有left

这是因为内循环改变了left和right的值,不做判断就会在里面的while循环一直循环

为什么以左边为基准值要从右开始找?(以右边为基准值要从左开始找)

如图,

八大排序算法之快速排序(Java实现)_第2张图片

思路

八大排序算法之快速排序(Java实现)_第3张图片

第二次写

package Sort;

import java.util.Arrays;

public class QuickSort {
	public static void main(String[] args) {
		QuickSort sort = new QuickSort();
		int arrs[] = {5,2,1,3,4};
		sort.qSort(arrs, 0, arrs.length-1);
		System.out.println(Arrays.toString(arrs));
	}

	public void qSort(int[] arrs,int left,int right) {
		if(left>=right)
			return;
		int pivot=partion(arrs, left, right);//基准值
		//左递归
		qSort(arrs, left, pivot-1);
		//右递归
		qSort(arrs, pivot+1, right);
	}
	public int  partion(int arrs[],int left,int right)
	{
		int pivotKey = arrs[left];//选左边第一个为基准值
		while(left=pivotKey)//右往左
			{
				right--;
			}
			//交换
			int temp=arrs[left];
			arrs[left]=arrs[right];
			arrs[right]=temp;
			while(left

时间:最好的情况,分区函数每次都分得很平均,这时候递归树的深度log2n ,每次分区排序时间为O(N) ,  所以最好的情况是O(nlogn)。最坏的情况,序列逆序,每次划分只比上次划分少一个记录的子序列,另一个序列为空,此时递归树画出来就是一颗斜树,大约需要进行n次分区操作,每次分区平均扫描N/2次,最终时间复杂度为N^2

总结:两个函数一个递归,一个每次分区排序返回基准值

和归并排序相似,也是用到了递归与合并,使子序列有序,最终整个序列有序

快排之所以快,每次交换是跳着换,而冒泡是相邻交换,首尾交换为例,快排直接1次对换,而冒泡要换n-1次

快排的优化

排序的快慢取决于每次取决于关键字在整个序列的位置,太小或者太大都会影响性能,而且在现实中,待排序序列极有可能是基本有序的,这样每次选择第一个数作为基准值极不合理。

所以就有了三数取中(九数取中也可以)

  • 即三个关键字取中间值,一般是左端中间右端三个数,也可以随机选取,随机数生成本身会带来时间上的开销,因此不予考虑
  • 覆盖替代交换,少掉很多不必要的交换
  • 在序列小于某个常数时7/50【来自参考资料】,使用插入排序,在小数组的情况下,插入排序要优于快排,因为快排用到了递归操作,在大数据量的情况下,则可以忽略这个影响
  • 尾递归优化?大话数据结构第四点

你可能感兴趣的:(八大排序算法,快速排序,排序算法)