为了offer系列——快速排序(C++),附测试用例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_15443203/article/details/73614032

offer必备三大算法之一——快速排序

平均时间复杂度:O(nlogn),和归并排序一样。尽管最坏时间复杂度很差,但因为它的平均性能非常好,故常用于实际当中。
稳定性:是一个不稳定的排序算法,不稳定发生在主元pivot和a[j]交换的时刻。 

基本步骤(算法导论分治思想的三步)如下:


1.分解:将数组A[p,..,r]以一个主元pivot(常取最后一个元素A[r])为界,划分为两个子数组(可能为空,如2,3,4),A[p,..,q-1]和A[q+1,..,r],是的前一个数组的每一个元素都小于或等于主元,后一个数组元素都大于主元。
2.解决:通过递归调用快速排序,对上述分割的两个子数组排序(递归的分解,直到都剩一个元素)。
3.合并:因为子数组都是原址排序(常用排序算法中,只有归并算法不是原址排序),数组都已经有序,故不需要合并操作。

r是主元的位置,i从p的前一个元素开始,j从p开始。若A[j]不大于主元,则把A[j]和A[++i]交换位置;反之,j++;直到遍历了所有元素,再将末尾的主元放在i++的位置。

程序如下:

//把原矩阵以主元pivot为界分成两个数组
void quick_s(int* A, int p, int r)
{
	if (p < r)    // 只有一个元素的数组不能分界
	{
		int q = partition(A, p, r);
		quick_s(A, p, q - 1); // 分别对两个数组再分解
		quick_s(A, q+1, r);
	}
}
//
int partition(int* A, int p, int r)
{
	int pivot = A[r];
	int i = p - 1;   //i从p的前一个开始!

	for (int j = p; j <= r-1; j++)        //j作为遍历数组的变量,j <= r-1
	{
		if (A[j] <= pivot) // 若A[j]不大于主元,则把A[j]和A[++i]交换位置;反之,j++;
		{
			i = i + 1;
			//int temp;
			int temp = A[j];
			A[j] = A[i];
			A[i] = temp;
			//swap(A[i], A[j]);
		}
	}  //循环一遍后,将末尾的主元放在i++的位置
	int temp2 = A[r];   //注意不要写成temp2 = pivot,结果是不一样的,大家可以试试。
	A[r] = A[i + 1];
	A[i + 1] = temp2;
	//也可以调用模板函数交换位置swap(A[i+1], A[r]);
	return i + 1;  //返回主元的位置
}

int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = { 2, 8, 7, 4, 6, 3 };
	cout << "Before quicksort:\n";
	for (auto x : a)
		cout << x << endl;
	quick_s(a, 0, 5);
	//swap(a[0], a[1]);
	cout << "After quicksort:\n";
	for (auto x : a)
		cout << x << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_15443203/article/details/73614032