快速排序(图文)

逻辑实现

以下列数组为例:

int[] list = new int[]{5,2,8,3,7,6,4,0,1,9};

数组
:随意指定数组中一个值(一般取数组中第一个元素),称为枢轴(pivot),拿数组中每个数据和枢轴对比,比枢轴大的放枢轴右边,比枢轴小的放枢轴左边

蓝色:往前移动
红色:往后移动

第一次比较:
这里写图片描述
第二次比较:
这里写图片描述
第三次比较:
这里写图片描述
第四次比较
这里写图片描述
。。。。。。以此类推,最后得到下面的数组
这里写图片描述

:以枢轴为切分点切分成两个数组
这里写图片描述

:对切分后的数组分别再调用步骤①、②进行排序,切分,最终完成排序
这里写图片描述
—————————————————————————————————————

实际上,上述逻辑存在一个问题
这里写图片描述
问题描述:
仔细查看步骤①的第三次比较,发现当3前移时,需要移动5和8共2个元素,如果此时5和3之间夹带的不止一个8,可能有100,1000个元素呢?岂不是要全部后移一位?这样是非常浪费时间

解决方案:
快速排序的逻辑虽然是拿数组中每个数据和枢轴对比,比枢轴大的放枢轴右边,比枢轴小的放枢轴左边,但算法其实是这样的

前置条件:
Ⅰ仍然指定数组中第一个元素为枢轴(pivot)
Ⅱ每次比较一定是枢轴和其他元素的比较
Ⅲ对比元素选取规则:
: 1.当前对比元素如果在枢轴左边,则下一个对比元素即当前对比元素的下标+1
: 2.当前对比元素如果在枢轴右边,则下一个对比元素即当前对比元素的下标-1

第一次比较:

第二次比较:
这里写图片描述

第三次比较
这里写图片描述

第四次比较
这里写图片描述

第五次比较
这里写图片描述

第六次比较
这里写图片描述

第七次比较
这里写图片描述

第八次比较
这里写图片描述

最终比较
这里写图片描述

可以看到,每次调换都只移动了2个元素的位置,节约了大部分时间。
步骤①完成改进后,其他步骤②③没有改变

—————————————————————————————————————

代码实现

定义快速排序方法

void quickSort(int[] list) {
	//调用快速排序真实方法,主要是为了调用方法时传参方便,只需要传入一个数组
	sort(list, 0, list.length-1);
}

定义快速排序真实方法

void sort(int[] list, int low, int high) {
	//定义枢轴
	int pivot;
	//low<higt,保证遍历时,左元素和右元素对比到下标一致时就结束
	if (low < high) {
	//此处代码代表的就是步骤①(1)
	pivot = compare(list, low, high);
	//对切分后的左边的数组调用递归排序
	sort(list, low, pivot - 1);
	//对切分后的右边的数组调用递归排序
	sort(list, pivot + 1, high);
	}
}

定义核心代码,元素比较与转换模块

int compare(int[] list, int low, int high) {
	记录枢轴的大小
	int pivotKey;
	//默认定义枢轴元素为左起第一个元素
        pivotKey = list[low];
        //low<higt,保证遍历时,左元素和右元素对比到下标一致时就结束
        while (low < high) {
		//上诉提到的元素对比规则Ⅲ中的第2条:
		//当前对比元素如果在枢轴右边,则下一个对比元素即当前对比元素的下标-1
		while (low < high && list[high] >= pivotKey) 
                high--;
	    //直到找到比枢轴小的元素,枢轴与对比元素进行交换
		swap(list, low, high);
		//上诉提到的元素对比规则Ⅲ中的第1条:
		//当前对比元素如果在枢轴左边,则下一个对比元素即当前对比元素的下标+1
		while (low < high && list[low] <= pivotKey) 
                low++;
	    //直到找到比枢轴大的元素,枢轴与对比元素进行交换
		swap(list, low, high);
	}
}

定义对调位置的函数

 void swap(int[] list,int low,int high){
	int middle = list[low];
	list[low]=list[high];
	list[high]=middle;
}

逻辑实现的内容是自己编写,图片也是自己用PPT做出来的截图的
代码实现参考自程杰老师的《大话数据结构》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值