快速排序,也是用的分而治之的算法,但是与归并不一样的,归并排序侧重的是最后怎么把子问题合并,分解子问题就是从中间分开。快排侧重于把子问题分开的部分,而不侧重合并
下面看个将数组从小到大排序的例子:
(1)两个索引,P1和P2。
P1的左边(包括P1)是比主元小的元素,,又边则是比主元大的元素。
P2遍历没有考察的元素
(2)随机选取主元。
在数组中,随机选取一个元素,令其作为标准,结束后其左边是比它小的元素,右边是比他大的元素。选取主元后,将主元放到数组最右边,方便考察。
(3)开始考察
4比3大,不动,P2右移
2比三小,将2和P1所指元素互换,P1和P2都右移
5比3大,仅P2右移
同上
0比3小,将0和P1指向的互换,P1和P2同时右移
P2到达末尾,将P1指向的元素与末尾元素互换,并返回P1作为找到的主元
下一步对左边和右边做同样的操作,最终得到结果
#include<iostream>
#include<time.h>
using namespace std;
// 随机选取主元并且把数组按照主元分解,并返回主元最后的位置
int Randomized_Partition(int A[], int l,int r)
{
int p = 0; // 交换媒介
int P1 = l;
int P2 = l; // 两个遍历下标
srand((time(NULL)));
int s = rand() % (r - l )+ 1 + l; // 随机选取主元
// 交换主元到末尾
p = A[s];
A[s] = A[r];
A[r] = p;
// 遍历分解原数组
while (P2 <r)
{
// P2遍历到比主元小的,就把这个元素放到左边
if (A[P2] <= A[r])
{
{
p = A[P1];
A[P1] = A[P2];
A[P2++] = p;
++P1;
}
}
// 如果没有,就直接把P2往下;
else
++P2;
}
// 把主元放中间
p = A[r];
A[r] = A[P1];
A[P1] = p;
// 返回主元现在的位置
return P1;
}
// 主递归函数
void Randomized_QuickSort(int A[], int l,int r)
{
// 递归出口
if (l >= r)
return;
int q = 0; // 主元所在位置
q = Randomized_Partition(A, l, r);
Randomized_QuickSort(A, l, q - 1); // 处理主元左边
Randomized_QuickSort(A, q, r); // 处理主元右边
}
int main()
{
int A[6] = { 3,2,5,6,0,4 };
cout << "原数组为:";
for (int i = 0; i < 6; ++i)
cout << A[i] << " ";
Randomized_QuickSort(A, 0, 5);
cout << endl<<"快速排序后得数组为:";
for (int i = 0; i < 6; ++i)
cout << A[i]<<" ";
cout << endl;
return 0;
}
期望时间复杂度(nlogn)