算法导论 改进快排(3)---栈深度 习题7-4

来源:互联网 发布:彩票源码系统php 编辑:程序博客网 时间:2024/05/22 04:57

问题:快排算法包含了两个对自身的递归调用,每次递归调用的信息存入栈中,操作系统给程序的栈空间是有限的,如果数组很大,则很容易造成栈溢出,这样程序就崩溃了。

思路: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




0 0
原创粉丝点击