问题:快排算法包含了两个对自身的递归调用,每次递归调用的信息存入栈中,操作系统给程序的栈空间是有限的,如果数组很大,则很容易造成栈溢出,这样程序就崩溃了。
思路:QUICKSORT中的第二个递归用一个循环控制结构来代替----尾递归
代码实现:
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
//交换两个数
void Swap(int & a, int &b)
{
int temp=b;
b=a;
a=temp;
}
//
int T_Partition(int *A, int p, int r)
{
int i=p-1;
for(int j=p;j<=r-1;j++)
{
if(A[j]<=A[r])
{
++i;
Swap(A[i],A[j]);
}
}
Swap(A[i+1],A[r]);
return i+1;
}
void Tail_QuickSort(int *A, int p, int r)
{
while(p<r)
{
int q=T_Partition(A,p,r);
if((q-p)<(r-q))
{
Tail_QuickSort(A,p,q-1);
p=q+1;
}
else
{
Tail_QuickSort(A,q+1,r);
r=q-1;
}
}
}
int main()
{
int A[9]={2,4,1,6,4,5,9,3,7};
for(int i=0;i<9;i++)
{
cout<<A[i]<<" ";
}
cout<<endl;
Tail_QuickSort(A,0,8);
for(int j=0;j<9;j++)
{
cout<<A[j]<<" ";
}
return 0;
}
解释程序:
以(q-p)<(r-q)为例,将if改成while后,因为第一次递归以后,变量p就没有用处了,所以可以将q+1赋值给p,再循环后,来一次T_Partition(A,p,r),
其效果等同于“Tail_QuickSort(A,q+1,r);”结果相同。但因采用迭代而不是递归的方法可以缩减堆栈深度,从而提高了整体性能。
注:转载自 http://blog.csdn.net/column/details/algorithms-my-answer.html?&page=2
1.尾递归的概念(引自维基百科):
“在计算机科学里,尾调用是指一个函数里的最后一个动作是一个函数调用的情形:即这个调用的返回值直接被当前函数返回的情形。这种情形下称该调用位
置为尾位置。若这个函数在尾位置调用本身(或是一个尾调用本身的其他函数等等),则称这种情况为尾递归,是递归的一种特殊情形。”
2.用n!的例子解释尾递归
根据这个定义,我们很容易写出来尾递归的程序,比如求最简单的n的阶乘,我们有如下代码,左边为普通递归方式,右边为尾递归方式:
int factorial(int n){ if ( n <= 1) return 1; else return n*factorial(n-1); } | int tailFactorial(int n, int result){ if (n <= 1) return result; else return tailFactorial(n-1,n*result); } |
我们从上面的程序可以看出,我们以计算5的阶乘为例进行说明:
factorial(5) {5 * factorial(4)} {5 * {4 *factorial(3)}} {5 * {4 * {3 *factorial(2}}} {5 * {4 * {3 * {2 *factorial()}}}} {5 * {4 * {3 * {2 * 1}}}} {5 * {4 * {3 * 2}}} {5 * {4 * 6}} {5 * 24} 120 | tailFactorial(5, 1) tailFactorial(4, 5) tailFactorial(3, 20) tailFactorial(2, 60) tailFactorial(1, 120) 120 |