您的位置:首页 > 编程语言 > C语言/C++

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

2017-06-23 10:25 190 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐