算法导论学习笔记(五):快速排序

快速排序是一种最坏情况运行时间为O(n*n),虽然这个最坏情况运行时间比较差,但快速排序通常都是用于排序的最

的实用选择,这是因为其平均性能相当好:期望的运行时间为O(nlgn),且O(nlgn)记号中隐含的常数因子很小。另

外,它还能够进行就地排序。


快速排序和合并排序一样,采用的都是分治思想。快排中利用该思想解决步骤为:

1、先从数组中取出一个数作为基数,基数的选择对排序效率的影响很大

2、分区,将比这个基数小的数全部放到它的左边,比基数大的数全部放到其右边

3、对左右两个区间重复第二步,直到每个区间只有一个数


下面结合代码来进一步理解快速排序。算法导论上一开始给出的基数选择就是直接选择待排序数组中最后一个元素作

基数,即对于数组a[N],以a[N-1]作为基数。以一般情况来讨论,当我们要进行排序的数组为a[p...r]时,选择a[r]为

数,然后将这个序列分为3部分,a[p...q-1],a[q], a[q+1, r],其中a[p...q-1]的元素都是小于基数的,a[q]就是基

数,a[q+1, r]的元素都大于基数。其实现代码如下:

int partition (int a[], int p, int r)
{
	int i = p - 1;
	for (int j = p; j < r; j++)
	{
		if (a[j] < a[r])
		{
			swap (a[++i], a[j]);
		}
	}
	swap (a[++i], a[r]);
	return i;
}
该函数的执行过程如下图:


这个函数最后返回的便是q,接下来我们便要对a[p...q-1]和a[q+1, r]重复上述步骤,直到只剩下一个元素。代码如下:

void quick_sort (int a[], int p, int r)
{
	if (p < r)
	{
		int q = partition (a, p, r);
		quick_sort (a, p, q - 1);
		quick_sort (a, q + 1, r);
	}
}

最后附上我自己的一个完整的代码,可以直接运行测试运行结果:

#include<iostream>
using namespace std;

void display (int a[], int n);
void swap (int& n, int& m);
int partition (int a[], int p, int r);
void quick_sort (int a[], int p, int r);

int main()
{
	int a[100];
	int n;
	while (cin >> n)
	{
		for (int i = 0; i < n; i++)
			cin >> a[i];
		quick_sort (a, 0, n - 1);
		display (a, n);
	}
	return 0;
}

void display (int a[], int n)
{
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
	cout << endl;
}

void swap (int& n, int& m)
{
	int temp;
	temp = n;
	n = m;
	m = temp;
}

int partition (int a[], int p, int r)
{
	int i = p - 1;
	for (int j = p; j < r; j++)
	{
		if (a[j] < a[r])
		{
			swap (a[++i], a[j]);
		}
	}
	swap (a[++i], a[r]);
	return i;
}

void quick_sort (int a[], int p, int r)
{
	if (p < r)
	{
		int q = partition (a, p, r);
		quick_sort (a, p, q - 1);
		quick_sort (a, q + 1, r);
	}
}

算法导论书上在最后还提供了几个改进的版本,如随机化版本,三数取中等,这些改进的版本基本都是在对基数选择

方法上进行改进的。有兴趣的朋友可以自己试试!


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值