排序算法之快速排序

一.快速排序原理

    快速排序最坏时间复杂度是n^2 。对于包含n个元素的输入序列而言,快速排序虽然最坏情况下时间复杂度很差,但是它的平均性能非常好为nlgn。快速排序通常是最好的选择。另外它还能进行原址排序。快速排序算法可以描述为:首先把输入序列分成两个部分A[p...q-1]和A[q+1...r]。使得A[p...q-1]部分都小于A[q]右半部分都大于A[q]。通过递归调用快速排序,不断对子序列排序完成整个排序过程。

伪代码描述:

                        quick_sort(A, p, r) 

                        if p < r

                                q = quicj_sort_one(A, p, r)

                                quick_sort(A, p, q - 1)

                                quick_sort(A, q+1,  r)

                       else

                                return; 

    这里关键是对quicj_sort_one的理解,它完成把小于和大于关键值Key的元素分别放在key元素位置的两侧。循环递归操作最终完成了排序的过程。先看看quicj_sort_one的实现过程:

static int quick_sort_one(void** ppvArray, int left, int right, DataCompare compare)
{
	int tmp_left = left;
	int tmp_right = right;
	
	if(left < right)
	{
		void* temp = ppvArray[right];
		do
		{
			while(tmp_left < tmp_right && compare(ppvArray[tmp_left], temp) < 0)
			{
				tmp_left++;
			}
			if(tmp_left < tmp_right)
			{
				ppvArray[tmp_right] = ppvArray[tmp_left];
				tmp_right--;
			}
			while(tmp_left < tmp_right && compare(ppvArray[tmp_right], temp) > 0)
			{
				tmp_right--;
			}
			if(tmp_left < tmp_right)
			{
				ppvArray[tmp_left] = ppvArray[tmp_right];
				tmp_left++;
			}	
		}while(tmp_left < tmp_right);

		ppvArray[tmp_left] = temp;
	}
	return (tmp_left);
}
      选取最后一个元素作为Key值,所有比Key大的数放到右边,小的放到左边。因此我们需要寻找左边比Key大的数(tmp_left),并把这个数填到tmp_right指向的位置。这个时候tmp_left为空,接着从后半部分寻找比Key小的数踢出来填充到前半部分空的位置。假设当期输入序列:3,1,4,2。

      1>把最后一个数2作为基准保存在临时变量tmp, 此时tmp_left=0,tmp_right=3.第一次从前向后找比2大的数,当tmp_left指向3这个数字符合要求。把3填到空出来的位置(由tmp_right指向)。完成了一次操作。得到序列:_,1,4,3。此时tmp_left=0(指向新的空位),tmp_right=2。
        2>从后往前找剔除比tmp值小的数,当tmp_right=1(值等于1)的时候满足要求。把它填到上一次的空位(tmp_left=0)。得到序列:1,_,4,3。

      3>此时发现空格位置左边的数都比tmp小,右边的数都比tmp大,完成一次排序。

      4>递归把tmp左边和右边分别操作即可得到最后的结果。

快速排序核心算法:

static int quick_sort_one(void** ppvArray, int left, int right, DataCompare compare)
{
	int tmp_left = left;
	int tmp_right = right;
	
	if(left < right)
	{
		void* temp = ppvArray[right];
		do
		{
			while(tmp_left < tmp_right && compare(ppvArray[tmp_left], temp) < 0)
			{
				tmp_left++;
			}
			if(tmp_left < tmp_right)
			{
				ppvArray[tmp_right] = ppvArray[tmp_left];
				tmp_right--;
			}
			while(tmp_left < tmp_right && compare(ppvArray[tmp_right], temp) > 0)
			{
				tmp_right--;
			}
			if(tmp_left < tmp_right)
			{
				ppvArray[tmp_left] = ppvArray[tmp_right];
				tmp_left++;
			}	
		}while(tmp_left < tmp_right);

		ppvArray[tmp_left] = temp;
	
		quick_sort_one(ppvArray, left, tmp_left - 1, compare);
		quick_sort_one(ppvArray, tmp_left + 1, right, compare);
	}
	return (0);
}


int quick_sort(void** ppvArray, size_t length, DataCompare compare)
{
	if(ppvArray == NULL || compare == NULL)
	{
		return (-1);
	}
	if(length < 2)
	{
		return (0);
	}
	return (quick_sort_one(ppvArray, 0, length-1, compare));
}

二.测试

写一个测试程序测试下结果:

int _tmain(int argc, _TCHAR* argv[])
{
	int anTest[] = {2, 8, 4, 90, 1000, -3 , 777};

	quick_sort(anTest, sizeof(anTest) / sizeof(anTest[0]));

	return 0;
}



      最后按照惯例把排序算法封装下再给快速排序用测试程序跑一遍。测试模块在前面已经说过了,因为排序算法的函数原型都是一样的只需要把排序函数换成快速排序就可以了。

————————————The End。

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值