快速排序

介绍

    快速排序也是基于分治法来实现的,这在合并排序中就有说到过。它的主要实现原理就是,在数组t[n]中,选出一个数作为比较值,然后小于这个数的值放左边,大于这个数的值放右边,它则在中间;然后递归依次去操作左边和右边,如此反复,直到非空,则比较完成,而结果就已经排序好了。

实现

    首先,先计算出中间值的位置:

int partition(int* a, int start, int end)
{
	/// 选出数组尾数为中间值
	int tail = a[end];
	int i = start - 1;
	/// 判断数组中哪些数小于尾数,则交换位置
	for (int j = start; j <= end - 1; ++ j)
	{
		if (a[j] < tail)
		{
			++ i;
			swap(a[j], a[i]);
		}
	}
	/// 最后,把尾数和右边第一个数交换位置
	swap(a[i + 1], a[end]);
	/// 返回中间数的下标
	return i + 1;
}

    1.此算法先把尾数当成比较值,即中间值
    2.然后从起始位置到结束位置遍历数组,比中间值小的放左边,比中间值大的放右边
    3.然后把中间值放到中间来,即右边数第一个位置
    4.然后返回中间位置

    然后就是递归调用了:

/// 快速排序
/// 原理是 选出数组中的一个值,然后比这个值小的数放到左边,
/// 比这个数大的放到右边,这个数放中间,一直这样分下去,就是
/// 一个排好序的数组
void quickSort(int* a, int start, int end)
{
	/// 判断数组非空
	if (start < end)
	{
		/// 计算中间值
		int mid = partition(a, start, end);
		/// 左边快速排序
		quickSort(a, start, mid - 1);
		/// 右边快速排序
		quickSort(a, mid + 1, end);
	}
}

    是不是很像合并排序呢? 不过此算法和合并有点不一样的地方是,它在计算中间值的时候顺便把数据已经大致排了一下,然后下面在根据左边和右边再排一次,而合并却是直接计算出中间值,然后再进行排序,最后再进行合并,而快速排序没有合并这说法。

#include <iostream>
#include <cstdint>
#include <algorithm>

using namespace std;

template<class T>
void print(T* t, int length)
{
	for (int i = 0; i < length; ++ i)
	{
		cout << t[i] << " ";
	}
	cout << endl << "-----------------------" << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[10] = {10, 1, 9, 3, 5, 8, 2, 6, 4, 7};
	int length = sizeof(a) / sizeof(a[0]);

	print(a, length);
	quickSort(a, 0, length - 1);
	print(a, length);

	return 0;
}

    结果如下:quickSort-result

quickSort-result

    由上面的代码,大家应该也看出来了,这里选取中间值是直接选取数组的最后一个。这样做有好也有坏,好处是方便,直接选取最后一个;坏处便是,这样效率有可能很低,为什么?因为如果选取的中间数导致2边的比例是8:1或者是9:1,那这样就很影响效率了。所以,这里再提供一个随机化版本,尽量把这种因素降到最低。

int randomizedPartition(int* a, int start, int end)
{
	/// 随机求出中间值 然后和末尾的值交换
	int mid = (rand() % (end - start + 1)) + start;
	swap(a[mid], a[end]);

	return partition(a, start, end);
}

void randomizedQuickSort(int* a, int start, int end)
{
	/// 判断数组非空
	if (start < end)
	{
		/// 计算中间值
		int mid = randomizedPartition(a, start, end);
		/// 左边快速排序
		randomizedQuickSort(a, start, mid - 1);
		/// 右边快速排序
		randomizedQuickSort(a, mid + 1, end);
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	srand(time(NULL));
	int a[10] = {10, 1, 9, 3, 5, 8, 2, 6, 4, 7};
	int length = sizeof(a) / sizeof(a[0]);

	print(a, length);
	cout << "randomizedQuickSort:" << endl;
	randomizedQuickSort(a, 0, length - 1);
	print(a, length);

	return 0;
}

    结果如下:randimerQuickSort

randimerQuickSort

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Z小偉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值