通俗易懂的快速排序-QUICKSORT

  “对于包含n个数的输入数组来说,快速排序是一种最坏情况时间为O(n^2)的排序算法,虽然最坏情况的时间复杂度很差,但是快速排序通常是实际排序应用中最好的选择”-《算法导论》第七章

  这篇文章将简单地描述快速排序的思路,代码实现。主要针对的是刚刚学习编程的新人,不是很能理解各种专业术语,被一些博客的高深劝退的人。这篇文章的语言很通俗易懂,代码也很简单

  一  快速排序的思想

    快速排序实际上运用到了分治的策略,要对一个无序数组进行排序。我们先可以从最简单的情况考虑,如果存在一个数组的有三个元素:a,b,c ,且a>b>c。要从小到大排序,我们找到b为中间值,就只需调换a,c的顺序。 面对一个更复杂的数组,我们也可以用同样的策略:选取该数组中的一个元素q,将小于q的元素放在q的左边,将大于q的元素放在q的右边。并用递归再对左边和右边数组进行再一次分治,重复进行直到整个数组都被排序,我们的排序就完成了。

  所以我们的递归思路很简单,就是找到q后,对q左边右边再此调用排序函数,递归的终止条件就是我们进行分治的区间只剩两个元素了。

   现在比较关键的是如何分治的问题。这里我们用了一个双指针的思想。我们可以通过两个指针来框出一个区间,这个区间的元素都是大于q的元素,我们不断把大于q的元素放入此区间,把小于q的元素放到此区间的左侧。一直到一边的指针碰到边界。

  实现这一分治策略的方法如下:我们的右指针不断向右移动,在这个过程中,如果经过的元素比q大,那我要框出的区间就应该扩张,因此我的左指针不动。但如果经过的元素比q小,则我的区间应保持不变,因此左指针随右指针向右移动。那如何把小于q的元素放在左边呢,很简单:我们只需要交换此时这个区间最右边的元素与最左边的交换,就实现了小于q的在左,大于q的在右的需求。

  接下来,我们考虑q的选取,因为对于q值不同的情况,这个排序需要执行的次数不一定,我们这里直接可以选取这个数组中最后一个元素,方便我们直接在数组上调换位置。当然,对元素的选取随机化,有助于保证我们的平均复杂度到较好的水平。

 到这里,快速排序的算法就已经清楚了。需要注意的是,我们需要将最后一个元素,即我们选取的q元素,放回数组中间。

  下图是此算法的一个演示

二  代码实现

//快速排序
#include <iostream>
#include <algorithm>
using namespace std;

int A[10000];
int n;

int partition(int l, int r) {
	int x = A[r];//x即我们选取分隔数组的标准值
	int i = l - 1, j = l;//左指针和右指针
	while (j <= r - 1) {
		if (A[j] <= x) {
			i = i + 1;//区间长度不变
			swap(A[i], A[j]);//将小于x的元素放在左边
		}
		j++;
	}
	swap(A[i + 1], A[r]);//处理我们的x值
	return i + 1;
}

void quick_sort(int l, int r) {
	if (l < r) {//递归跳出条件
		int q = partition(l, r);
		quick_sort(l, q - 1);
		quick_sort(q + 1, r);
	} else
		return;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &A[i]);
	}
	quick_sort(1, n);
	for (int i = 1; i <= n; i++) {
		printf("%d ", A[i]);
	}
	return 0;
}

 完成!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值