排序算法之快速排序算法

快速排序算法是一种较为快速的排序算法,其平均时间复杂度为O (n*logn)。其算法思想是在序列中选取参考元素,将比参考元素小的元素都放到参考元素的左边,将比参考元素大的元素都放到参考元素的右面,这就完成了一趟排序。最后应用分治思想分别对参考元素两边的子序列进行排序。算法中一趟排序的步骤描述如下:


1. 选取参考元素,一般情况下以排序序列(设为array[])的第一个元素作为参考元素,设key为参考元素的初始下标,则key=0,参考元素表示为array[key]。

2. 设置头尾指针,头指针(start)指向序列的第一个元素,尾指针(end)指向序列的最后一个元素。

3. 首先从为指针开始,end指针不断前移(即end指针不断自减1),知道array[end]<array[key]或者end == start时,停止前移。交换array[end]与参考元素的值,并且更新参考元素的最新下标。

4. 当第3步完成后,不断后移start指针(即start指针不断自加1),直到出现array[start] >array[key]的值或者start == end时,停止后移。交换array[start]与参考元素的值,并且更新参考元素的下标。

5. 重复第3、4步骤,直到start == end,则一趟排序结束。

例如:对于以下序列进行从小到大的排序

   下标       0          1         2       3       4      5      6      7     8

序列A:       2          2        4        9       7      6      3     1      5

初始时,      key=0                                                                   end=8

   start=0

首先,尾指针end不断前移,当移到下标为7处是 A[7] < A[key],所以交换A[7]和A[key]

此时序列变为:

  下标       0          1         2       3       4      5      6     7     8

序列A:       1         2        4        9       7      6      3     2      5

    s                                                             e

                                                                                 k=7

现在 临到头指针s不断后移,直到s=2时,A[2] > A[k],所以交换A[2] 、A[k]的值,交换后序列变为:

下标          0          1         2       3       4      5      6      7     8

序列A:       1          2         2        9       7      6      3    4      5

                                         s                                       e

                                         k=2


现在又临到,尾指针前移了,直到移到e=2处,此时满足s==e,循环退出,一趟排序完成。如下图所示:



从这可以看出,在头指针或尾指针移动的过程中不仅要判断A[start]或A[end]与A[key]之间的大小关系

还要判断start是否小于end,如果是则循环完毕。在上里中如果不判断start是否小于end,则end会一直递减直到0,或者小于0,此时数组会出现越界的情况。

另外,从上面的例子可以看出,快速排序是不稳定的排序算法。


不稳定是指序列中的两个相等元素,在排序后他们的相对位置发生变化的现象。

在一开始是A[0] == A[1] == 2, 但一趟排序完成是,A[0]中的2跑到了A[2]的位置上,由A[1]的前面跑到了A[1]的后面

排序算法的C++实现代码:

void swap(vector<int>& vec,int left, int right)
{
	/*用不开辟临时变量的方法交换两个数的值*/


	vec[left] = vec[left] + vec[right];
	vec[right] = vec[left] - vec[right];
	vec[left] = vec[left] - vec[right];


	/*使用临时变量的方法交换两个数的值*/
	//int tmp = vec[left];
	//vec[left] = vec[right];
	//vec[right] = tmp;
}
void QuickSort(vector<int>& vec, int left, int right)
{
	int key = left;
	int r = right;
	int l = left;
	while (left < right)   //此循环控制整个排序算法的结束(包含多趟排序)
	{ 
		/*
		* 序列尾指针right不断向前移动,直到不满足条件
		* 注意: 循环终止条件中的 left < right 是必要的,如果没有此条件,可能会出现
		* right一直递减最终小于left的情况
		*/
		while (vec[right] >= vec[key] && left < right)
			right--;
		//交换尾指针指向的元素与参考元素的值,并且更新参考元素的小标
		//注意:此处应判断while循环是否是因为vec[right] >= vec[key]条件不满足而终止,因为只有这种情况下
		//我们才需要交换这两个元素的值
		if (left < right)
		{
			swap(vec,key,right);
			key = right;
		}
		
		// 序列头指针,不断前移,直到不满足前移条件为止
		while (vec[left] <= vec[key] && left < right)
			left++;
		if (left < right)
		{
			swap(vec,key,left);
			key = left;
		}
		
	}
	//递归调用,对参考元素的两边的子序列分别进行排序
	//注意: 为防止数组下标越界,应该做一些必要的判断
	if (key -1 > l)
		QuickSort(vec,l,key-1);
	if (key + 1 < r)
		QuickSort(vec,key+1,r);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值