七大排序算法之改进算法系列(七)——快速排序

快速排序(Quick Sort):

快速排序的原理:参考这篇 快速排序(过程图解)

快速排序的代码实现:

#include <iostream>

using namespace std;

void swap(int k[], int low, int high)
{
	int temp;

	temp = k[low];
	k[low] = k[high];
	k[high] = temp;
}

int Partition(int k[], int low, int high)
{
	int point;

	point = k[low];

	while (low < high)
	{
		while (low < high && k[high] >= point)  //一定要注意这里是大于等于,如果                         
                                                        //换成大于号,当有相同的元素进                
                                                        //行比较时会出现死循环
		{
			high--;
		}
		swap(k, low, high);

		while (low < high && k[low] <= point)  //同时注意这里是小于等于
		{
			low++;
		}
		swap(k, low, high);
	}

	return low;
}

void QSort(int k[], int low, int high)
{
	int point;

	if (low < high)
	{
		point = Partition(k, low, high);

		QSort(k, low, point - 1);

		QSort(k, point + 1, high);
	}
}

void QuickSort(int k[], int n)
{
	QSort(k, 0, n - 1);
}

int main()
{
	int i, a[10] = { 4, 2, 5, 0, 3, 9, 1, 7, 6, 8 };

	cout << "排序前的数组是:";
	for (i = 0; i < 10; i++)
	{
		cout << a[i];
	}
	cout << endl;

	QuickSort(a, 10);

	cout << "排序后的数组是:";
	for (i = 0; i < 10; i++)
	{
		cout << a[i];
	}
	cout << endl;

	return 0;
}

 实现结果:

 在快速排序中,我们会选取一个关键字,然后想尽办法将它放到一个位置,是的它左边的值都比它小,右边的值都比它大,我们把这样的关键字叫做枢轴(privot)。

显然枢轴的选取对快排的效率是有影响的。除了枢轴的选取,还有其他的一些因素也能对快排的效率造成影响,

快速排序的优化:

1)优化选取枢轴

之前代码中的枢轴的选取都是直接取第一个数字,如果这个数字大小比较靠中间还好,如果比较偏大或者偏小对排序都不好。

三数取中法:即取三个关键字进行排序,将中间的作为枢轴,一般取左端、右端和中间三个数。

还有三数取中法的改进版本,九数取中法,是将三数取中法做3次,再取出最中间的数。

2)优化不必要的交换

3)优化小数组时的排序方案

在数组较小的时候,我们直接用简单排序中表现较好的直接插入排序。

4)优化递归操作

使用尾递归

对于尾递归的解释,可以参考百度百科这篇讲解

当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。编译器可以做到这点,因为递归调用是当前活跃期内最后一条待执行的语句,于是当这个调用返回时栈帧中并没有其他事情可做,因此也就没有保存栈帧的必要了。通过覆盖当前的栈帧而不是在其之上重新添加一个,这样所使用的栈空间就大大缩减了,这使得实际的运行效率会变得更高。


快速排序的时间复杂度和空间复杂度分析:

时间复杂度:

最优:O(nlogn)

最差:O(n²)

平均:O(nlogn)

空间复杂度:

最优:O(logn)

最差:O(n)

平均:O(logn)


快速排序的稳定性分析:

由于快速排序中,关键字的比较和交换都是跳跃进行的,因此,快速排序是一种不稳定的排序算法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值