快速排序

/*
快速排序:(分治思想: 分、治、合)
	不同版本:(效率越来越高) 
		1)、轴值取中间元素,分割时从序列的左端l,右端r向序列中间扫描。交换逆置元素,直到l、r相交。
		2)、轴值取中间元素,分割时从序列的左右两端交替检查空闲位置,将逆置元素移动到空闲位置上,
			 直到l、r相交,最后将轴值放到空闲位置。
		3)、当快速排序的子数组小于某个长度n时,不必继续递归。最后对整个数组进行一次插入排序。n=28、9、16等值。
		4)、随机化的快速排序,轴值取随机值。
		5)、随机找到3个元素,取中间值作为轴值。
*/

#include <iostream>
#include <time.h>
using namespace std;

#define N 16

void PrintArr(int *pnArr, int nLen)
{
	int i;
	for (i = 0; i < nLen; i++)
	{
		cout<<pnArr[i]<<" ";
	}
	cout<<endl;
}

int SelectPivot(int nLeft, int nRight)
{
	return (nLeft + nRight) / 2;
}

int RandomSelectPivot(int nLeft, int nRight)
{
	return rand()%(nRight - nLeft + 1) + nLeft;
}

int MidValue(int *pnArr, int nPos1, int nPos2, int nPos3)
{
	if (pnArr[nPos1] >= pnArr[nPos2] && pnArr[nPos1] <= pnArr[nPos3] ||
		pnArr[nPos1] >= pnArr[nPos3] && pnArr[nPos1] <= pnArr[nPos2])
	{
		return nPos1;
	}

	if (pnArr[nPos2] >= pnArr[nPos1] && pnArr[nPos2] <= pnArr[nPos3] ||
		pnArr[nPos2] >= pnArr[nPos3] && pnArr[nPos2] <= pnArr[nPos1])
	{
		return nPos2;
	}

	if (pnArr[nPos3] >= pnArr[nPos1] && pnArr[nPos3] <= pnArr[nPos2] ||
		pnArr[nPos3] >= pnArr[nPos2] && pnArr[nPos3] <= pnArr[nPos1])
	{
		return nPos3;
	}
	return 0;
}
int Random3SelectPivot(int *pnArr, int nLeft, int nRight)
{
	srand(time(NULL));
	int nPos1 = rand()%(nRight - nLeft + 1) + nLeft;
	int nPos2 = rand()%(nRight - nLeft + 1) + nLeft;
	int nPos3 = rand()%(nRight - nLeft + 1) + nLeft;	
	
	return MidValue(pnArr, nPos1, nPos2, nPos3);
}
 
//1、轴值取中间元素,分割时从序列的左端l,右端r向序列中间扫描。交换逆置元素,直到l、r相交。
int Partition1(int *pnArr, int nLeft, int nRight)
{
	int nLPos = nLeft;
	int nRPos = nRight;
	int nPivotValue = pnArr[nRight];	//将轴值存放在临时变量中

	while (1)
	{
		while (pnArr[nLPos] <= nPivotValue && nLPos < nRPos)
		{
			nLPos++;
		}
		while (pnArr[nRPos] >= nPivotValue && nLPos < nRPos)
		{
			nRPos--;
		}
		if (nLPos >= nRPos)
		{
			break;
		}
		swap(pnArr[nLPos], pnArr[nRPos]);
	}

	swap(pnArr[nRight], pnArr[nLPos]);
	return nLPos;

}

//从小到大排序
void QuickSort1(int *pnArr, int nLeft, int nRight)
{
	if (nLeft < nRight)
	{
		int nPivotPos = Random3SelectPivot(pnArr, nLeft, nRight);
		swap(pnArr[nPivotPos], pnArr[nRight]);

		nPivotPos = Partition1(pnArr, nLeft, nRight);
		
		QuickSort1(pnArr, nLeft, nPivotPos - 1);
		QuickSort1(pnArr, nPivotPos + 1, nRight);
	}
}

//2、轴值取中间元素,分割时从序列的左右两端交替检查空闲位置,将逆置元素移动到空闲位置上,
//	 直到l、r相交,最后将轴值放到空闲位置。
int Partition2(int *pnArr, int nLeft, int nRight)
{
	int nLPos = nLeft;
	int nRPos = nRight;
	int nPivotValue = pnArr[nRight];	//将轴值存放在临时变量中

	while (nLPos != nRPos)
	{
		while (pnArr[nLPos] <= nPivotValue && nLPos < nRPos)
		{
			nLPos++;
		}
		if (nLPos < nRPos)
		{
			pnArr[nRPos] = pnArr[nLPos];
			nRPos--;
		}
		while (pnArr[nRPos] >= nPivotValue && nLPos < nRPos)
		{
			nRPos--;
		}
		if (nLPos < nRPos)
		{
			pnArr[nLPos] = pnArr[nRPos];
			nLPos++;
		}
	}
	pnArr[nLPos] = nPivotValue;

	return nLPos;
}
//从小到大排序
void QuickSort2(int *pnArr, int nLeft, int nRight)
{
	if (nLeft < nRight)
	{
		int nPivotPos = SelectPivot(nLeft, nRight);
		swap(pnArr[nPivotPos], pnArr[nRight]);

		nPivotPos = Partition2(pnArr, nLeft, nRight);
		
		QuickSort2(pnArr, nLeft, nPivotPos - 1);
		QuickSort2(pnArr, nPivotPos + 1, nRight);
	}
}


int Partition3(int *pnArr, int nLeft, int nRight)
{
	int nLPos = nLeft;
	int nRPos = nRight;
	int nPivotValue = pnArr[nRight];	//将轴值存放在临时变量中

	while (nLPos != nRPos)
	{
		while (pnArr[nLPos] <= nPivotValue && nLPos < nRPos)
		{
			nLPos++;
		}
		if (nLPos < nRPos)
		{
			pnArr[nRPos] = pnArr[nLPos];
			nRPos--;
		}
		while (pnArr[nRPos] >= nPivotValue && nLPos < nRPos)
		{
			nRPos--;
		}
		if (nLPos < nRPos)
		{
			pnArr[nLPos] = pnArr[nRPos];
			nLPos++;
		}
	}
	pnArr[nLPos] = nPivotValue;

	return nLPos;
	
}

void InsertSort(int *pnArr, int nLen)
{
	int i, j;
	for (i = 1; i < nLen; i++)
	{
		int nTmp = pnArr[i];
		for (j = i; j > 0 && pnArr[j - 1] > nTmp; j--)
		{
			pnArr[j] = pnArr[j-1];
		}
		pnArr[j] = nTmp;
	}
}


//当快速排序的子数组小于某个长度n时,不必继续递归。最后对整个数组进行一次插入排序。n=28、9、16等值。
void QuickSort3(int *pnArr, int nLeft, int nRight)
{
	if (nRight - nLeft + 1> 9)
	{
		int nPivotPos = SelectPivot(nLeft, nRight);
		swap(pnArr[nPivotPos], pnArr[nRight]);
		nPivotPos = Partition3(pnArr, nLeft, nRight);

		QuickSort3(pnArr, nLeft, nPivotPos - 1);
		QuickSort3(pnArr, nPivotPos + 1, nRight);
	}
	else 
	{
		InsertSort(pnArr, nRight - nLeft + 1);
	}
}


int main()
{
	int nArr[N] = {0};
	int i;
	srand(time(NULL));

	for (i = 0; i < N; i++)
	{
		nArr[i] = rand() % 100;  //rand(nMax - nMin + 1) + nMin ----> [nMin, nMax]
	}

	PrintArr(nArr, N);
	QuickSort1(nArr, 0, N - 1);
	PrintArr(nArr, N);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值