快速排序C++实现

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

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

主框架如下:

template
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(A, i - 1, j, A[j]); //k保存交换最后的左边界
	swap(A, k, j);		                     //交换左边界和轴值,相当于把轴值插入到排序好的位置
	qsort(A, i, k - 1);                     //轴值往左排序
	qsort(A, k + 1, j);                     //轴值往右排序
}

findpiovt函数找一个轴值

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

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

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

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

template
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
using namespace std;
template
void swap(E A[], int a, int b) {
	int temp = A[a];
	A[a]=A[b];
	A[b]=temp;
}

template
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 int findpivot(E A[], int i, int j) {return (i + j) / 2;}

template
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(A, i - 1, j, A[j]);
	swap(A, k, j);
	qsort(A, i, k - 1);
	qsort(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<

说一下时间复杂度

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

你可能感兴趣的:(排序)