快速排序

    还记得曾哥淡定的哼唱"七月份的前奏是狮子座~,八月份的尾巴也是狮子座~',狮子座的尾巴也是校园招聘的开始,祝愿毕业生们都能够找到满意的工作。如果你拿到太多的offer难以选择的时候,那就给每一份offer定上各项指标,算出权值,最后再用效率超高的快速排序来进行排序。

一. 算法描述

    快速排序:快速排序采用分治法进行排序,首先是分割,选取数组中的任意一个元素value(默认选用第一个),将数组划分为两段,前一段小于value,后一段大于value;然后再分别对前半段和后半段进行递归快速排序。其实现细节如下图所示:


二. 算法分析

平均时间复杂度:O(nlog2n)

空间复杂度:O(n) 

稳定性:不稳定

三. 算法实现

/********************************************************
*函数名称:Split
*参数说明:pDataArray 无序数组;
*		   iBegin为pDataArray需要快速排序的起始位置
*          iEnd为pDataArray需要快速排序的结束位置
*函数返回:分割后的分割数位置
*说明:    以iBegin处的数值value作为分割数,
           使其前半段小于value,后半段大于value
*********************************************************/
int Split(int *pDataArray,int iBegin,int iEnd)
{
	int pData = pDataArray[iBegin];    //将iBegin处的值作为划分值

	while (iBegin < iEnd)    //循环分割数组,使其前半段小于pData,后半段大于pData
	{
		while (iEnd > iBegin && pDataArray[iEnd] >= pData)    //从后向前寻找小于pData的数据位置
			iEnd--;

		if (iEnd != iBegin)
		{
			pDataArray[iBegin] = pDataArray[iEnd];    //将小于pData数据存放到数组前方
			iBegin++;

			while (iBegin < iEnd && pDataArray[iBegin] <= pData)
				iBegin++;
			
			if (iBegin != iEnd)
			{
				pDataArray[iEnd] = pDataArray[iBegin];    //将大于pData数据存放到数组后方
				iEnd--;
			}
		}
	}

	pDataArray[iEnd] = pData;    //此时iBegin=iEnd,此处存储分割数据pData
	return iEnd;
}

/********************************************************
*函数名称:QSort
*参数说明:pDataArray 无序数组;
*		   iBegin为pDataArray需要快速排序的起始位置
*          iEnd为pDataArray需要快速排序的结束位置
*说明:    快速排序递归函数
*********************************************************/
void QSort(int* pDataArray, int iBegin, int iEnd)
{
	if (iBegin < iEnd)
	{
		int pos = Split(pDataArray, iBegin, iEnd);    //获得分割后的位置
		QSort(pDataArray, iBegin, pos - 1);           //对分割后的前半段递归快排
		QSort(pDataArray, pos + 1, iEnd);             //对分割后的后半段递归快排
	}
}

/********************************************************
*函数名称:QuickSort
*参数说明:pDataArray 无序数组;
*		   iDataNum为无序数据个数
*说明:    快速排序
*********************************************************/
void QuickSort(int* pDataArray, int iDataNum)
{
	QSort(pDataArray, 0, iDataNum - 1);
}

四. 算法优化

    快排选用数组第一个元素作为分割元素,如果是一个已经基本有序的数组,那么时间复杂度将会提升到O(n2);可以从数组中随机选择一个元素作为划分数据,这样即使针对基本有序的数据来说,效率同样达到(nlog2n),优化后分割函数如下所示:
int Split(int *pDataArray,int iBegin,int iEnd)
{
	int rIndex = rand() % (iEnd - iBegin + 1);    //随机获得偏移位置

	int pData = pDataArray[iBegin + rIndex];    //将iBegin+rIndex处的值作为划分值

	while (iBegin < iEnd)    //循环分割数组,使其前半段小于pData,后半段大于pData
	{
		while (iEnd > iBegin && pDataArray[iEnd] >= pData)    //从后向前寻找小于pData的数据位置
			iEnd--;

		if (iEnd != iBegin)
		{
			pDataArray[iBegin] = pDataArray[iEnd];    //将小于pData数据存放到数组前方
			iBegin++;

			while (iBegin < iEnd && pDataArray[iBegin] <= pData)
				iBegin++;
			
			if (iBegin != iEnd)
			{
				pDataArray[iEnd] = pDataArray[iBegin];    //将大于pData数据存放到数组后方
				iEnd--;
			}
		}
	}

	pDataArray[iEnd] = pData;    //此时iBegin=iEnd,此处存储分割数据pData
	return iEnd;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值