快速排序的运行时间依赖于划分是否平衡,而平衡与否又依赖于用于划分的元素。如果划分是平衡的,那么快速排序算法性能与归并排序一样。如果划分是不平衡的,那么快速排序的性能就接近于插入排序了。
#include<iostream>
using namespace std;
//快速排序
template<class T> int partition(T *a,int first,int end) //实现了对子数组A[p..r]的原址重排
{
int x = a[end-1];
int i = first-1;
for(int j=first;j<=end-1;++j)
{
if(a[j-1] <= x)
{
++i;
swap(a[i-1],a[j-1]);
}
}
swap(a[i],a[end-1]);
return i+1;
}
template<class T> void quickSort(T *a,int first,int end)
{
if(first<end)
{
int mid = partition(a,first,end);
quickSort(a,first,mid-1);
quickSort(a,mid+1,end);
}
}
template<class T>void print(T *a,int num)
{
for(int i=0;i<num;++i)
cout<<a[i]<<ends;
}
int main()
{
int a[] ={5,2,4,6,1,3};
//char a[]="HelloWorld!";
int num = sizeof(a)/sizeof(a[0]);
quickSort(a,1,num);
print(a,num);
return 0;
}
quickSort分别递归调用了左边的子数组和右边的子数组。儿第二个递归调用并不是必须的。我们可以用一个循环控制结构来代替它。这一技术成为尾递归
template<class T> void tailRecursiveQuickSort(T *a,int first,int end) //尾递归
{
while(first<end)
{
int mid = partition(a,first,end);
tailRecursiveQuickSort(a,first,mid-1);
first = mid+1;
}
}
编译器通常使用栈来存储递归执行过程中的相关信息,包括每一次递归调用的参数等。最新调用的信息存在栈的顶部,而第一次调用的的信息存在栈的底部。当一个过程被调用时,其相关信息呗压入栈中;当它结束时,其信息则被弹出。栈深度是在一次计算中会用到的栈空间的最大值。