快速排序

基本思想

通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部

分记录继续进行排序,以达到整个序列有序的目的。

核心函数partition

public static int partition(int[] a, int low, int high) {
		//用子表的第一个记录作为中枢值
		int pivotKey = a[low];
		while(low < high) {
			while(low < high && a[high] >= pivotKey) {
				high--;
			}
			//将比中枢值小的放到低端
			swap(a, low, high);
			while(low < high && a[low] <= pivotKey) {
				low++;
			}
			//将比中枢值大的放到高端
			swap(a, low, high);
		}
		return low;
	}
//排序算法中用的比较频繁 
	public static void swap(int[] test,int i,int j) {
		int temp = test[i];
		test[i] = test[j];
		test[j] = temp;
	}

分析

partition函数要做的,就是先选取子表当中的关键字,比如第一个关键字,然后想尽办法将它放到一个位置,使得他左边的值都比它小,右边的值都比它大。

举例:int[] test ={50,10,90,30,70,40,80,60,20};

1. 程序开始执行,此时Iow=0high=test.length -1=9,我们将test[0]赋值给枢轴变量pivotkey

2.进入while循环。test[8] =20<pivotkey=50,不执行high- -语句,然后执行swap(a, low, high),将比中枢值小的放到低端。

至于内层为什么用while而不用if?

举个例子:int[] test = {50,10,90,30,70,40,80,60,65};此时test[8]>pivotkey, 执行high- -,然后进行交换,将test[7]与test[0]交换了,但是test[7]>pivotkey,此时不应该进行交换的,如果使用while的话,直到比pivotkey小时才进行交换。但使用if排序不会出错,后面代码会再交换回来,因为执行了一些不必要的操作,所以性能上会慢一点。建议使用while


3.low = 2 high = 8  test[low]>pivotkey 交换test[2]与test[8]


4.high = 5 low=2  test[high]<pivotkey 交换test[5]与test[2]

5.low = 4  high = 5 test[low]>pivotkey 交换test[4]与test[5]

6.low=high=5;退出循环,此时枢轴左边的值都比50小,右边都比50大

 

quickSort代码

public static void quickSort(int[] a, int low, int high) {
    	//中枢值
    	int pivot = 0;
    	if (low < high) {
			pivot = partition(a,low,high);
			quickSort(a, low, pivot - 1);
			quickSort(a, pivot + 1, high);
		}
    }

快速排序优化

1.优化选取枢轴

如果给定数组第一个元素并不是中间数,比如{9,1,5,8,3,7,4,6,2},我们选取9作为枢轴,经过一轮partition()函数后


所以对于枢轴的选取将会很大程度的影响性能。这里提出了“三数取中”的方法。

		//计算数组中间元素的下标
		int mid = low + (high - low) / 2;
		//交换左端右端数据,保证左端较小
		if(a[low] > a[high]) {
			swap(a, low, high);
		}
		//交换中间右端数据,保证中间较小
		if(a[mid] > a[high]) {
			swap(a, high, mid);
		}
		//交换中间左端数据,保证左端较小
		if(a[mid] > a[low]) {
			swap(a, low, mid);
		}
		//此时a[low]已经为整个序列左中右三个关键字的中间值
		//用子表的第一个记录作为中枢值
		int pivotKey = a[low];

2.优化不必要的交换

while(low < high) {
			while(low < high && a[high] >= pivotKey) {
				high--;
			}
			//将比中枢值小的放到低端
			//swap(a, low, high);
			a[low] = a[high];
			while(low < high && a[low] <= pivotKey) {
				low++;
			}
			//将比中枢值大的放到高端
			a[high] = a[low];
			//swap(a, low, high);
		}
		a[low] = pivotKey;
		return low;

还有一些优化的操作我这里就不一一赘述了,大家有兴趣可以去看相关书籍

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_36959304/article/details/80316469
文章标签: 排序算法 数组
个人分类: 算法 java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

快速排序

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭