namespace htx{
//1.快速排序
//<1>源码 <2>伪代码 <3>时间复杂度分析
//--------<1>源码---------
//如果数组的元素不是基本数据类型,而是对象,那么对应的类需要重载
//快速排序:从小到大 1->2
template<class T>
void quicksort12(T *A,int p,int r)
{
if(p < r)
{
int q = no_partition12(A,p,r);
quicksort12(A,p,q-1);
quicksort12(A,q+1,r);
}
}
template<class T>
int no_partition12(T *A,int p,int r)
{
T x = A[r];
int i = p - 1;
for(int j = p; j < r; j++)
{
//如果数组A的元素是类对象,
//那么只有当该类重载了“<=”运算符后才能使用本模板
//(也就是只有当该类重载了“<=”运算符后才能通过编译),下同
if(A[j] <= x)
{
i = i + 1;
exchange(A[i],A[j]);
}
}
exchange(A[i+1],A[r]);
return i+1;
}
//快速排序:从大到小 2->1
template<class T>
void quicksort21(T *A,int p,int r)
{
if(p < r)
{
int q = no_partition21(A,p,r);
quicksort21(A,p,q-1);
quicksort21(A,q+1,r);
}
}
template<class T>
int no_partition21(T *A,int p,int r)
{
T x = A[r];
int i = p - 1;
for(int j = p; j < r; j++)
{
if(A[j] >= x)
{
i = i + 1;
exchange(A[i],A[j]);
}
}
exchange(A[i+1],A[r]);
return i+1;
}
//元素交换
template<class T>
void exchange(T &a,T &b)
{
//如果出现数组越界,是不能使用try-catch来捕捉的
T m = a;
a = b;
b = m;
}
/*
<p>调用简例:</p><p>array[10];</p><p>htx::quicksort12(array,0,9);</p>
*/
/*--------<2>伪代码---------
QUICKSORT(A,p,r)
if p < r
q = PARTITION(A,p,r)
QUICKSORT(A,p,q-1)
QUICKSORT(A,q+1,r)
PARTITION(A,p,r)
x = A [ r ]
i = p - 1
for j = p to r - 1
if A[ j ] <= x
i = i + 1
exchange A [ i ] with A [ j ]
exchange A [ i+1 ] with A [ r ]
return i + 1
*/
/*--------<3>时间复杂度分析---------
最好:O(n) = nlog(2)n
平均:O(n) = nlog(2)n
最坏:O(n) = n^2
提示:可以按照描述自己画一下图
1.根据上述伪代码可知,快速排序函数是分两路递归的函数
2.那么将这个函数的递归路径画成二叉树的形式,设同一个函数体里面的两个子递归路径是同一层,即二叉树的两个子节点
3.同一父节点下的两个子节点就是同一个函数体内的两个递归调用的“代价”(就是花多少时间)
4.现在,假设“所有”父节点下的两个子节点的代价是成比例的,本例设为 1:9
5.有了比例(1:9),我们就可以算出这个二叉树的高度了,假设为 h
6.假设数组有n个元素,那么根节点的值就是n,即第一次循环的代价是c*n(c是常数,下同)
7.而位于末端的所有子节点的代价“至少”为1(有可能是2),因为PARTITION的循环次数至少为1
8.那么 n * (9/10)^h = 1 得到 h = log(10/9)n (如 log(a)b : 以a为底b的对数)
9.而二叉树每一层的代价和 <= c*n ,那么 总代价 = c*n*log(10/9)n
10.那么再在最好的情况下的比例是1:1,此时的 总代价 = c * n * log(2/1)n = c*n*log(2)n = nlog(2)n
11.所以最好的情况下是 O(n) = nlog(2)n;
12.如果你给的待排序数组数据是随机的,那么一直发生1:9这样悬殊的比例的概率是很小的。
13.也就是说比1:9的情况好,那么平均情况下就是接近 nlog(2)n 了。
14.至于最坏的情况,这里给个例子: 2 3 4 5 6 1 ,按照代码执行,代价为 5 4 3 2 1
15.写成公式: (1+(n-1)) * n / 2 = n^2/2 所以 最坏的情况下 O(n) = n^2
*/
}