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

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

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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值