快速排序的算法思想及示例

快速排序概念:

       快速排序(Quicksort)是对冒泡排序的一种改进。

       快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

快速排序算法介绍:

       设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它左边,所有比它大的数都放到它右边,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

一趟快速排序的算法是:

1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]的值交换;

4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]的值交换;

5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

快速排序算法演示:

假设有如下数组:

下标

0

1

2

3

4

5

数据

6

2

7

3

8

9

创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)。

我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较:

下标

0

1

2

3

4

5

数据

3

2

7

6

8

9

i=0 j=3 k=6

接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:

下标

0

1

2

3

4

5

数据

3

2

6

7

8

9

i=2 j=3 k=6

称上面两次比较为一个循环。

接着,再递减变量j,不断重复进行上面的循环比较。

在本例中,我们进行一次循环,就发现i和j“碰头”了:他们都指向了下标2。于是,第一遍比较结束。得到结果如下,凡是k(=6)左边的数都比它小,凡是k右边的数都比它大:

下标

0

1

2

3

4

5

数据

3

2

6

7

8

9

如果i和j没有碰头的话,就递加i找大的,还没有,就再递减j找小的,如此反复,不断循环。注意判断和寻找是同时进行的。

然后,对k两边的数据,再分组分别进行上述的过程,直到不能再分组为止。

注意:需要获得正确的排序,还要根据对左右两侧的子数组进行排序操作,才能得到最终的排序结果。

冒泡排序性能分析:

时间复杂度:

当数据有序时,以第一个关键字为基准分为两个子序列,前一个子序列为空,此时执行效率最差。

当数据随机分布时,以第一个关键字为基准分为两个子序列,两个子序列的元素个数接近相等,此时执行效率最好。

所以,数据越随机分布时,快速排序性能越好;数据越接近有序,快速排序性能越差。

空间复杂度:

快速排序在每次分割过程中,需要一个空间存储基准值,而快速排序的大概需要Nlog2N次的分割处理,所以占用的空间也是Nlog2N个。

算法稳定性:

在快速排序中,相等元素可能会因为分区而交换顺序,所以他是一种不稳定的算法。

快速排序代码示例:

package sort;

import java.util.Random;

public class QuickSort {
	public static void main(String[] args) {
		int[] arr = {6,2,7,3,8,9};
		System.out.print("数组排序前结果:\t");
		for(int numArr : arr) {
			System.out.print(numArr+"\t");
		}
		System.out.println();
		QuickSort quickSort = new QuickSort();
		quickSort.quickSort(arr, 0, arr.length-1);
	}
	public int division(int[] arr, int left, int right) {
		//
		int base = arr[left];
		while(left < right) {
			while(left < right && arr[right] >= base) {
				right--;
			}
			arr[left] = arr[right];
			while(left < right &&  arr[left] <= base) {
				left ++;
			}
			arr[right] = arr[left];
		}
		arr[left] = base;
		return left;
	}
	
	public void quickSort(int[] arr, int left, int right) {
		if(left < right) {
			int base = division(arr, left, right);
			System.out.format("base= %d: \t",arr[base]);
			for(int numArr: arr) {
				System.out.print(numArr+"\t");
			}
			System.out.println();
			quickSort(arr, left, base-1);
			quickSort(arr, base+1, right);
		}
	}
}

结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值