快速排序

快速排序

算法描述:

快速排序又称划分交换排序,首先选择一个"基准"(基准的选择有多种,一般以Array[0]),从数组右边开始j=Array.length-1,j--的寻找小于"基准"数据,从左边i=0,i++的寻找大于"基准"数据,然后让小于"基准"的数据都放在左边,让大于"基准"的数据都放在右边,当i==j时,交换Array[i]与"基准"。这一趟下来数组划分成了两个子序列,这就是分治思想的分,然后递归的对左右两边的子序列,即可完成排序。

快速排序的步骤:

我们以数组int[]a={7,5,3,2,9,10,8,4,6,1};这个数组为例来说明一下快速排序到底是怎么进行的。

第1步:找基准值

所谓的基准值,顾名思义就是以它为基准进行比大小。通常来说,我们选取数组的第一个数为基准值。在数组a里基准值就是7.

第2步:比大小

先从数组的最右边开始往左边找比基准值小的第一个数,然后从数组的最左边开始往右找比基准值大的第一个数。那么为什么要这么找呢?因为现在我们要把数组从小到大排序,所以要找出比基准值小的数放到基准值的左边,找出比基准值的数放在基准值的右边。
那么在数组a里,从左往右找,第一个比7大的数就是9,我们把它的坐标记为i;从右往左找,第一个比7小的数就是1,我们把它的坐标记为j。

第3步:交换

找到之后,如果这个时候i<j,那么就交换这两个数,因为i=4,j=9,符合条件,将9和1进行交换。现在数组变成了int[]a={7,5,3,2,1,10,8,4,6,9};
如果j>=i,那么不做处理
为什么还要判断i和j的大小呢?就像第二步说的,我们要找出比基准值小的数放到基准值的左边,找出比基准值的数放在基准值的右边。所以如果i<j的话,交换就达到目的了,如果i>=j,比基准值小的数就在基准值的左边,比基准值大的数已经在基准值的右边了,这时候就没必要交换了。

第4步:继续查找

在i<j的前提下,继续向右查找比基准值大的数,往左找比基准值小的数,然后交换。
在我们的例子中,10和6、8和4都符合交换的条件,所以数组就变成了
int[]a={7,5,3,2,1,6,4,8,10,9};这时候i=6,j=7

第5步:交换基准值到合适的位置

当查找继续进行,这时候i=j=6,已经不满足继续查找和交换的条件了,那么我们应该怎么办呢?答案就是把a[6]和基准值交换,因为i=j的时候说明已经到了一个分界线的位置,分界线左边的数比基准值小,分界线右边的数比基准值大,而这个分界线就是我们的基准值,所以把它和a[i]交换,这时候数组就变成:
int[]a={4,5,3,2,1,6,7,8,10,9};

第6步:重复

对基准值左右两边的两个子数组重复前面五个步骤直至排序完成。

时间复杂度:O(n*lgn)
空间复杂度:O(1)
java实现:
public static void quickSort(int[] arr, int left, int right) {
		if (left < right) {
			int index = partion(arr, left, right); //查找基准分割点
			quickSort(arr, left, index - 1); //左边序列递归排序
			quickSort(arr, index + 1, right); //右边序列递归排序
		}
	}

	public static int partion(int[] arr, int left, int right) {
		int pivot = arr[left]; //第一个作为基准点
		int i = left;
		int j = right;
		while (i < j) {
			while (pivot <= arr[j] && i < j) { //从右边查找小于基准的数据
				j--;
			}
			while (pivot >= arr[i] && i < j) { //从左边查找大于基准的数据
				i++;
			}
			if (i < j) { //左右交换
				swap(arr, i, j);
			}
		}
		arr[left] = arr[i]; //基准划分点
		arr[i] = pivot; 
		return i;
	}

	public static void swap(int[] arr, int left, int right) {
		int tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
	}
GitHub地址: https://github.com/xckNull/Algorithms-introduction.git
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值