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

来源:互联网 发布:淘宝买账号被骗 编辑:程序博客网 时间:2024/04/26 07:29

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;}