首页 > 代码库 > 算法学习之排序算法:快速排序

算法学习之排序算法:快速排序

快速排序:快速排序是对冒泡排序的一种改进。它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。


一趟快速排序的具体做法:

1、附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey。

2、首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录互相交换。

3、从low所指位置起向后搜索,找到第一个关键字大于pivotkey的记录和枢轴记录互相交换。

4、重复2、3步直至low=high为止。

举例说明上面步骤:

初始关键字:49   38   65   97   76   13   27   49

1、附设low和high以及设枢轴记录的关键字为pivotkey:

                     49   38   65   97   76   13   27  49

                      ↑(low)                                        ↑(high)

                      ↑(pivotkey)

2、从high所指位置向前搜索,找到第一个小于pivotkey的记录(此处为27)和枢轴记录互相交换:

                     27   38   65   97   76   13  49   49

                      ↑(low)                                 ↑(high)

                                                                 ↑(pivotkey)

3、从low所指位置向后搜索,找到第一个大于pivotkey的记录(此处为65)和枢轴记录互相交换:

                    27   38  49   97   76   13   65   49

                                   ↑(low)                   ↑(high)

                                   ↑(pivotkey)

4、重复2、3步直至low=high为止。

                  27   38   13   97   76   49   65   49

                                 ↑(low)           ↑(high)

                                                      ↑(pivotkey)

                 27   38   13   49   76   97   65   49

                                       ↑(low)    ↑(high)

                                       ↑(pivotkey)

                  27   38   13   49   76   97   65   49

                                       ↑(low=high)

                                       ↑(pivotkey)

上面给出的是一趟快速排序的过程,整个快速排序的过程可递归进行。若待排序列中只有一个记录,显然已经有序,否则进行一趟快速排序后再分别对分割所得的两个子序列进行快速排序。


示例代码1(C语言描述):

/*********************************************************************
 Author:李冰 date:2014-9-11
 Email:libing1209@126.com
 @array: the pointer to the records
 @low high
*********************************************************************/

//数据交换
void Swap(int *num1, int *num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}

//一趟快速排序过程
int Partition(int array[], int low, int high)
{
	int pivotkey = array[low];
	
	while(low < high){
		while(low < high && array[high] >= pivotkey)
			high--;
		Swap(&array[low], &array[high]);

		while(low < high && array[low] <= pivotkey)
			low++;
		Swap(&array[low], &array[high]);
	}

	return low;
}

//递归形式快速排序
void QuickSort(int array[], int low, int high)
{
	int pivotloc;

	if(low < high){
		pivotloc = Partition(array, low, high);	
		QuickSort(array, low, pivotloc - 1);
		QuickSort(array, pivotloc + 1, high);
	}
}

上面的一趟快速排序过程中用到了3此记录的赋值操作,即swap函数中的三次赋值,但对枢轴记录的赋值是多余的,因为只有在一趟快速排序结束时,即low=high时的位置才是枢轴记录的最后位置。因此改写算法如下:

示例代码2(C语言描述):

//一趟快速排序
int Partition(int array[], int low, int high)
{
	int pivotkey = array[low];
	
	while(low < high){
		while(low < high && array[high] >= pivotkey)
			high--;
		array[low] = array[high];

		while(low < high && array[low] <= pivotkey)
			low++;
		array[high] = array[low];
	}
	array[low] = pivotkey;

	return low;
}
//快速排序
void QuickSort(int array[], int low, int high)
{
	int pivotloc;

	if(low < high){
		pivotloc = Partition(array, low, high);	
		QuickSort(array, low, pivotloc - 1);
		QuickSort(array, pivotloc + 1, high);
	}
}

注意:

1、就平均时间而言,快速排序是目前被认为是最好的一种内部排序方法。

2、快速排序被认为是,在所有同数量级(O(nlogn))的排序方法中,其平均性能最好的。

3、在选择枢轴值的时候,可以依照“三者取中”的法则来选取枢轴记录,即比较low、high和mid所指值中中间的那个作为枢轴值,可以大大改善快速排序在最坏情况下的性能。


总结:

1、从时间上看,快速排序的平均性能优于其他各种排序方法。

2、从空间上看,快速排序需要一个栈空间来实现递归。


参考文献:

1、《数据结构(C语言版)》严蔚敏 吴伟东 编著

2、http://blog.csdn.net/morewindows/article/details/6668714

3、http://blog.csdn.net/to_be_it_1/article/details/37866391


                      

算法学习之排序算法:快速排序