快速排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_36959304/article/details/80316469

基本思想

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

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

核心函数分区

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;
	}

分析

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

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

 

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

 

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

至于内层为什么用而而不用,如果?

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

 

 

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

 

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

 

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

 

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

 

快速排序代码

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作为枢轴,经过一轮分区()函数后

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

		//计算数组中间元素的下标
		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;

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

阅读更多
想对作者说点什么?

博主推荐

换一批

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