快速排序C++实现

快速排序的思想近似于BST里根节点与左右节点的关系。

大致思想是选择一个轴值,然后把数组里比轴值小的放在左边,比轴值大的放在右边,通过递归处理两边的数组达到总体排序的效果。

主框架如下:

template<class E>
void qsort(E A[], int i, int j) {
	if (j <= i) return;                      //不处理数组大小0和1的情况
	int pivotindex = findpivot(A, i, j);     //找一个轴值
	swap(A, pivotindex, j);                  //把轴值放到数组末尾
	int k = partition<E>(A, i - 1, j, A[j]); //k保存交换最后的左边界
	swap(A, k, j);		                     //交换左边界和轴值,相当于把轴值插入到排序好的位置
	qsort<E>(A, i, k - 1);                     //轴值往左排序
	qsort<E>(A, k + 1, j);                     //轴值往右排序
}

findpiovt函数找一个轴值

影响快排时间复杂度最大的就是轴值的选择,对于未排序的数组而言,轴值的选择最好是随机的,这里简单的取数组中间的值作为轴值。

template<class E> int findpivot(E A[], int i, int j) {return (i + j) / 2;}

partition函数用来交换数组轴值左右的元素

不需要保证交换后数组是有序的,这交给接下来分隔后的数组去做。

template<class E>
int partition(E A[], int l, int r, E& pivot) {
	do {
		while (A[++l] < pivot);                  //左边界往右移动直到找到大于轴值的值
		while ((r != 0) && (A[--r] > pivot));    //右边界往左移动直到找到小于轴值的值
		swap(A, l, r);					  //交换数组里的这两个值
	} while (l < r);                            //左右边界交错即停止
	swap(A, l, r);                              //交错后会有一次不必要的交换,这里把它调整过来
	return l;				//返回此时的左边界
}

测试代码如下:

#include<iostream>
using namespace std;
template<class E>
void swap(E A[], int a, int b) {
	int temp = A[a];
	A[a]=A[b];
	A[b]=temp;
}

template<class E>
int partition(E A[], int l, int r, E& pivot) {
	do {
		while (A[++l] < pivot);
		while ((r != 0) && (A[--r] > pivot));
		swap(A, l, r);
	} while (l < r);
	swap(A, l, r);
	return l;
}

template<class E> int findpivot(E A[], int i, int j) {return (i + j) / 2;}

template<class E>
void qsort(E A[], int i, int j) {
	if (j <= i) return;
	int pivotindex = findpivot(A, i, j);
	swap(A, pivotindex, j);
	int k = partition<E>(A, i - 1, j, A[j]);
	swap(A, k, j);
	qsort<E>(A, i, k - 1);
	qsort<E>(A, k + 1, j);
}

int main() {
	int arr[] = {3,2,1,4,4,6,3,2,1,5,7,2,1,6,8,10};
	qsort(arr,0,(sizeof(arr)/sizeof(int))-1);
	for(auto i : arr){
		cout<<i<<' ';
	}
}

说一下时间复杂度

一般认为快排的时间复杂度为θ(nlogn),最差情况就是轴值的选择没有很好的分隔数组,选择了最大或最小的那个数,那么在下一次递归排序中需要排序的数组大小和原来差不多大,此时的时间复杂度就变为O(n²)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值