C/C++快速排序

快速排序

说明

主要是学习数据结构,真的做什么,请直接使用标准算法库stl中的排序

视频讲解
【王道计算机考研 数据结构】 https://www.bilibili.com/video/BV1b7411N798/?p=90&share_source=copy_web&vd_source=734d9fe130776e8ae82b2b5371a5f5b8

基本思想:
通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,
则可分别对这两部分记录继续进行排序,以达到整个序列有序。
具体就是,
在待排序表L[1…n]中任取一个元素pivot作为枢轴(或基准,通常取首元素),
通过一趟排序将待排序表划分为独立的两部分L[1…k-1]和L[k+1…n],
使得L[1…k-1]中的所有元素小于pivot,L[k+1…n]中的所有元素大于等于pivot,则pivot放在了其最终位置L(K)上,这个过程称为一次“划分”。
然后分别递归地对两个子表重复上述过程,直至每部分内只有一个元素或空为止,即所有元素放在了其最终位置上。

一趟快速排序的具体做法是:
(注意,我这里枢轴并不选取第一个!)
附设两个指针分别为 low 和 high,它们的初始分别指向开头和结尾,设枢轴记录的关键字为 pivotkey,枢轴位置记为pStart
注意到有额外的变量pivokey记录枢轴元素,枢轴元素位置可以用来干别的,相当于原本枢轴元素位置“清空”了
在这里插入图片描述
把第一个元素,赋值给pStart所指位置。
这样开头就被“清空”了,而且它的元素也没有丢失,被放到了pStart所指位置。
在这里插入图片描述
首先,从high所指位置起向前搜索,找到第一个关键字小于 pivotkey的记录赋值给low所指位置,
然后,从 low 所指位置起向后搜索,找到第一个关键字大于pivotkey的记录赋值给high所指位置,
重复这两步直至low和high二者相遇为止。
在这里插入图片描述
二者相遇的这个位置,即为枢轴元素的最终位置。
将枢轴元素(由pivokey记录)填入这里。

代码

请注意,在

	while (low < high)//从表两端交替的向中间扫描
	{
		while (low < high && *high >= pivot)
			high--;
		*low = *high;//将比枢轴小的记录移到低端

		while (low < high && *low <= pivot)
			low++;
		*high = *low;//将比枢轴大的记录移到高端
	}

之前,得把开头“清空”

以记录中任意元素为枢轴的代码

/*功能:快速排序
* 输入:
* start:要排序的数组开头指针
* end:要排序的数组结尾指针
* 输出:
* 其它:
* 顺序由小到大
* 直接在原本的数组中排序(直接处理原来的数组)
* 对整个数组使用时,比如testArray1[8] = {……};quickSort(testArray1, testArray1+7);
*/
void quickSort(int* start, int* end);

int* partition(int* low, int* high)
{
	用中间位置的元素作为枢轴
	//int* pStart = low + (high - low) / 2;//记录这个元素本来的位置
	//int pivot = *pStart;//记录作为枢轴的元素

	//用随机位置的元素作为枢轴
	int* pStart = low + (rand()%(high - low+1));//记录这个元素本来的位置
	int pivot = *pStart;//记录作为枢轴的元素

	//把开头“腾空”
	*pStart = *low;

	while (low < high)//从表两端交替的向中间扫描
	{
		while (low < high && *high >= pivot)
			high--;
		*low = *high;//将比枢轴小的记录移到低端

		while (low < high && *low <= pivot)
			low++;
		*high = *low;//将比枢轴大的记录移到高端
	}
	*low = pivot;//枢轴元素存放到最终位置
	return low;//枢轴存放最终位置
}

void quickSort(int* start, int* end)
{
	srand(time(0));

	int* pivotPos = NULL;//保存枢轴位置
	if (start < end)
	{
		pivotPos = partition(start, end);//划分并确认枢轴位置		
	}
	if (start < pivotPos - 1)
	{
		quickSort(start, pivotPos - 1);//递归排序左子表
	}
	if (pivotPos + 1 < end)
	{
		quickSort(pivotPos + 1, end);//递归排序右子表
	}
}

//快速排序测试
void test4(void)
{
	int testArray1[8] = { 49,38,65,97,76,13,27,49 };
	cout << "原本" << endl;
	myArrayPrint(testArray1, 8);
	cout << "快速排序排序" << endl;
	quickSort(testArray1, testArray1+7);
	myArrayPrint(testArray1, 8);

	cout << endl;

	int testArray2[20] = { 78,84,77,10,48,11,13,85,65,21,15,30,56,12,14,34,55,34,98,43 };
	cout << "原本" << endl;
	myArrayPrint(testArray2, 20);
	cout << "快速排序排序" << endl;
	quickSort(testArray2, testArray2+19);
	myArrayPrint(testArray2, 20);
}

测试结果
在这里插入图片描述

直接以第一个元素为枢轴的代码

它直接第一个当枢轴,就把第一个清空了,完成了我划分开始的操作
下面的代码,是以第一个元素作为枢轴的

/*功能:快速排序
* 输入:
* start:要排序的数组开头指针
* end:要排序的数组结尾指针
* 输出:
* 其它:
* 顺序由小到大
* 直接在原本的数组中排序(直接处理原来的数组)
* 对整个数组使用时,比如testArray1[8] = {……};quickSort(testArray1, testArray1+7);
*/
void quickSort(int* start, int* end);

/*功能:用第一个元素将待排序序列划分成左右两部分
* 输入:
* start:要排序的数组开头指针
* end:要排序的数组结尾指针
* 返回:
* 枢轴存放最终位置
* 其它:
* 在快速排序中调用
*/
int* partition(int* low, int* high)
{	
	int pivot = *low;//记录作为枢轴的元素,并用第一个元素作为枢轴
	while (low < high)//从表两端交替的向中间扫描
	{
		while (low < high && *high >= pivot)
			high--;
		*low = *high;//将比枢轴小的记录移到低端
		while (low < high && *low <= pivot)
			low++;
		*high = *low;//将比枢轴大的记录移到高端
	}
	*low = pivot;//枢轴元素存放到最终位置
	return low;//枢轴存放最终位置
}

void quickSort(int* start, int* end)
{
	int* pivotPos = NULL;//保存枢轴位置
	if (start < end)
	{
		pivotPos = partition(start, end);//划分并确认枢轴位置		
	}
	if (start < pivotPos - 1)
	{
		quickSort(start, pivotPos - 1);//递归排序左子表
	}
	if (pivotPos + 1 < end)
	{
		quickSort(pivotPos + 1, end);//递归排序右子表
	}
}


//快速排序测试
void test4(void)
{
	int testArray1[8] = { 49,38,65,97,76,13,27,49 };
	cout << "原本" << endl;
	myArrayPrint(testArray1, 8);
	cout << "快速排序排序" << endl;
	quickSort(testArray1, testArray1+7);
	myArrayPrint(testArray1, 8);

	cout << endl;

	int testArray2[20] = { 78,84,77,10,48,11,13,85,65,21,15,30,56,12,14,34,55,34,98,43 };
	cout << "原本" << endl;
	myArrayPrint(testArray2, 20);
	cout << "快速排序排序" << endl;
	quickSort(testArray2, testArray2+19);
	myArrayPrint(testArray2, 20);
}

测试结果
在这里插入图片描述

讨论

在这里插入图片描述
我本人觉得没什么必要,因为正常人肯定是对乱序的记录去做排序,这样用开头元素就好,反正是随机的。
如果能提前知道是逆序的记录,那直接调用颠倒之类的就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜哥万岁万岁万万岁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值