【练习10】
Ackerman函数的递归实现与迭代实现。Ackerman(4,1)以上都无法计算出来。
原文地址:http://blog.csdn.net/pku_zzy/article/details/51933791
1、递归实现
int ack(int m,int n)
{
if (m==0)
return n+1;
else if (n==0)
return ack(m-1,1);
else
return ack(m-1,ack(m,n-1));
}
2、迭代实现
int Ack(int M,int N)
{
int top=0,m,n;
int stack[10000][4]={{M,N}};//记录信息m,n,Ack(m,n),跳转出口种类;
while (true)
{
m=stack[top][0];
n=stack[top][1];
if (m==0)
stack[top][2]=n+1;
else if (n==0)
{
top++;
stack[top][0]=m-1;
stack[top][1]=1;
stack[top][3]=1;
continue;
l1:
stack[top][2]=stack[top+1][2];
}
else
{
top++;
stack[top][0]=m-1;
top++;
stack[top][0]=m;
stack[top][1]=n-1;
stack[top][3]=2;
continue;
l2:
stack[top][1]=stack[top+1][2];
stack[top][3]=3;
continue;
l3:
stack[top][2]=stack[top+1][2];
}
if (top==0)
break;
top--;
switch (stack[top+1][3])
{
case 1:goto l1;
case 2:goto l2;
case 3:goto l3;
}
}
return stack[0][2];
}
【练习11】汉诺塔递归问题 Hanoi Recursion
函数的参数:移动盘子的个数,从哪个柱子移动到哪个柱子,以哪个柱子为辅助,共计4个参数。
一般递归程序转换为循环的步骤:
(1)递归函数主体的转换:转换为循环,while(1)即可;
(2)递归调用的转换:将当前参数、局部变量…(活动记录)压栈;参照调用方式改变参数,继续循环;
(3)函数执行结束——递归返回的处理:若栈空,整个递归过程结束,跳出循环;否则,将调用者的活动记录弹出栈,恢复其环境,继续循环;
(4)递归函数不同入口的区分——返回地址的处理:上例:ENTRANCE、FIRST、SECOND,活动记录的一部分,与参数、局部变量一同压栈、出栈,在循环主体中,根据当前活动记录的入口值,执行不同代码
具体递归代码可参见:http://blog.csdn.net/kkkkkxiaofei/article/details/8333644/
【练习12】递归求解powerset(S),即S集合的所有子集。
http://www.mhhe.com/engcs/compsci/sahni/c1/E5.HTM
http://bbs.csdn.net/topics/380062729
S是集合,Sn是子集,SA是可选子集,Ps是幂集。
解:算法Powerset(SN,SA,PS)// S是集合,SN是子集,SA是可选子集,PS是幂集
Powerset 1[递归出口]
If SA={ } then
{PS<—PS+SN.
Return.}
Powerset 2[把SN加入PS]
PS<—PS+SN
Powerset 3[递归调用]
FOR ( 所有 Item 属于SA)
DO {Powerset(SN 并{Item},
SA<—SA-{item},PS)}
Return.
下面这个算法,也是把集合做了一个0-1设置,从0~2^n逐个打印
#include <stdio.h>
#include <string.h>
#include <assert.h>
/* 猜测结果 */
void print_sub_set(const char *set_str)
{
//assert(set_str);// 集合是否存在
const size_t LEN = strlen(set_str);
const size_t PEAK = 0x1 << LEN;// 上限值
size_t i, j;
assert(LEN < sizeof(size_t) * 8);// 集合是否过大
for (i = 0; i < PEAK; ++i)
{
for (j = 0; j < LEN; ++j)
{
if ((i >> j) & 0x1)
{
printf("%c", set_str[j]);
}
}
printf("\n");
}
}
/* 测试代码 */
int main()
{
print_sub_set("ABCDE");
return 0;
}
本文探讨了Ackerman函数的递归与迭代实现,并通过汉诺塔问题展示了递归问题如何转换为循环解决。此外,还提供了求解集合所有子集的两种方法。
2718

被折叠的 条评论
为什么被折叠?



