快速排序

一)算法介绍

快速排序是对冒泡排序的一种改进算法,属于不稳定排序

基本思想:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都要比另一部分的所有数据都要小,按照此方法对数据进行快速排序,以达到整个数据变成有序列表。

备注:快速排序是一种适用于数据量越大,数据分布越混乱的算法,一般被认为性能是最好的。

不稳定排序:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;

 

二)算法原理

基本原理

第一步:首先设定一个分界值(基数),将数据分割成左右两部分。

第二步:将大于分界值的数据排列到右边小于分界值的数据排列到左边

第三步:然后左右两边的数据又可以独立排序,对左侧数据又可以取一个分界值,分割成左右两部分,对右侧数据也取一个分界值,分割成左右两部分。按左边存放比分界值小,右边存放比分界值大的规则进行排序。

第四步:不断重复第三步,对数据进行取分界值(基数),分割成左右部分,按左小右大的规则排序,直到排序完成。

 

算法步骤图解

源数据:int[] nums = {83, 23, 333, 24, 534, 234, 81};

先设定一个分界值,一般是假设第0个下标元素为分界值(基数)。

查找规则:从左往右查找比分界值(基数)大的元素,从右往左查找比分界值(基数)小的元素。

 

第一遍排序:取元素83为分界值(基数)、从右往左比较,83>81,先记录元素81的下标值,再从左往右比较,83<333,先记录元素333的下标值,把元素81和元素333的位置交换。再把分界值(基数)调到中间,把元素24(元素333的后一个元素)和分界值(基数)83交换位置。

排序结果为:[24, 23, 81, 83, 534, 234, 333]

 

第二遍排序:先把左侧数据进行处理,取元素24为分界值(基数),从右往左比较,24>23,交换24和23的位置,左侧无数据比较。

排序结果为:[23, 24, 81, 83, 534, 234, 333]

 

第三遍排序:此时左侧的数据都已经排列好,再把右侧数据进行处理,取元素534为分界值(基数)。534>333,交换534和333的位置,再比较333>234,交换333和234的位置。排序完成

最终排序结果为:[23, 24, 81, 83, 234, 333, 534]

 

算法排序效果图:

算法复杂度:

最差情况:T(n) = O(n^2)

最好情况:T(n) = O(log2N)

O(log2N)的含义:将一个数据集分成两半,然后将分开的每一半再分成两半,依此类推。

O(Nlog2N)的含义将一个数据集分成两半,然后将分开的每一半再分成两半,依此类推,在此过程中同时遍历每一半数据。

 

三)算法源码

步骤简介:先取一个分界值(基数),按比基数大排右边,比基数小排左边的规则,不断递归对数据进行取分界值(基数),分割成左右两部分数据,再排序等操作,直到数据排序完成。

/**
 * 快速排序
 * @param nums
 * @return
 */
public static int[] quickSort(int[] nums) {
	if (nums == null) {
		return null;
	}
	return quick(nums, 0, nums.length-1);
}
	
private static int[] quick(int[] nums, int left, int right) {
	if (left > right) {
		return null;
	}
		
	// 取第一个元素作为比较的基数
	int base = nums[left];
		
	// 记录第一位和最后一位的临时下标
	int low = left;
	int high = right;
		
	// 循环
	while (low != high) {
			
		// 先从high往low的方向找,如果nums[high]比基数大,就一直往low方向找,直到找到比基数小的值,然后把下标记录起来
		while (low < high && nums[high] >= base) {
			high--; // 记录的都是比基数值小的下标,需要放置到基数左边的元素
		}
			
		// 再从low往high找,如果nums[low]比基数小,就一直往high方向找,直到找到比基数大的值,然后把下标记录起来
		while (low < high && nums[low] <= base) {
			low++; // 记录的都是比基数值大的下标,需要放置到基数右边的元素
		}
			
		// 把比基数大的值(nums[low])和比基数小的值(nums[high])交换位置。比基数大的值排列在左边,比基数小的值排列在右边
		if (low < high) {
			int temp = nums[low];
			nums[low] = nums[high];
			nums[high] = temp;
		}
	}
		
	// 第low的值放置到源数据第left下标位置
	nums[left] = nums[low];
	// 把基数放置到中间
	nums[low] = base;
		
	// 把左侧数据再进行取分界值、分割成左右两部分、进行排序
	quick(nums, left, low-1);
		
	// 把右侧数据再进行取分界值、分割成左右两部分、进行排序
	quick(nums, low+1, right);
		
	// 返回值
	return nums;
}

 

识别二维码关注个人微信公众号

本章完结,待续、欢迎转载!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值