函数递归赶羊c语言 函数递归调用c语言

求狼羊白菜过河的C语言编程题详解 。希望不要用数组解决 。按照你的要求 , 不使用数组 。
我的思路,起点货物狼、羊、白菜,人一直在开船,通过递归函数,每次靠岸尝试装卸货方案,直到找满足条件的方案 。将可行方案存放在结构链表中形成操作流水打印 。
人狼羊菜存储方式模拟4位2进制 , 用1111表示 , 每位表示一个单位,1存在 , 0不存在 。
#includestdio.h
#includemalloc.h
typedef enum{false,true}bool;
typedef struct opRecord//用结构链表记录操作流水
{
int p1_take;//p1载货值
int p1_goAd;//p1卸货值
int p2_take;//p2载货值
int p2_goAd;//p2卸货值
int cen;//递归层号
struct opRecord *next;
}OPR;
OPR *oprHead;
OPR *oprTail;
char *getName(int b);//获取对应名称
int beEaten(int p1,int p2);//检查是否发生被吃事件,发生返回1 , 未发生返回0
int toShip(int *p1,int *p2,int *ship,bool f);//递归函数:上船人及任意一组合,返回状态,1:方案可行;0:方案不可行
int getFist(int pn);//获取物品组合中第一个
void addLog(int p1_take,int p1_goAd,int p2_take,int p2_goAd,int cen);//将有效操作添加进日志,cen相同,将视为修改覆盖
void printfLog();//打印操作流水
OPR *findLogBycen(int cen);//通过cen查找流水 。有返回节点指针 。无返回NULL
int count=1;
int flag=0;//标识变量=1成立;=0不成立
int cen=0;
int main()
{
int p1=111,ship=1000,p2=0000;//p1,p2分别表示两岸,4位数每一位分别表示人狼羊菜,位数值1表示存在,0表示不存在
oprHead=(OPR *)malloc(sizeof(OPR));
oprHead-next=NULL;
oprTail=NULL;
printf("河岸有人、狼、羊、白菜要过河,船每次载人及一物,为避免人上船后狼吃羊或羊吃菜\n开始生成方案:\n\n");
if(toShip(p1,p2,ship,0))
{
printf("\n开始生成结果报告:\n");
printfLog();
}
else
printf("无可行方案?。n");
return 0;
}
void addLog(int p1_take,int p1_goAd,int p2_take,int p2_goAd,int cen)//将有效操作添加进日志,cen相同 , 将视为修改覆盖,
{
OPR *oprNew=findLogBycen(cen);
if(oprNew==NULL)//通过查找 。确认无记录,新增记录
{
oprNew=(OPR *)malloc(sizeof(OPR));
oprNew-p1_take=p1_take;
oprNew-p1_goAd=p1_goAd;
oprNew-p2_take=p2_take;
oprNew-p2_goAd=p2_goAd;
oprNew-cen=cen;
oprNew-next=NULL;
if(oprHead-next==NULL)
oprHead-next=oprNew;
else
oprTail-next=oprNew;
oprTail=oprNew;
}
else//查找发现已有记录,修改
{
oprNew-p1_take=p1_take;
oprNew-p1_goAd=p1_goAd;
oprNew-p2_take=p2_take;
oprNew-p2_goAd=p2_goAd;
}
}
OPR *findLogBycen(int cen)//通过cen查找流水 。有返回节点指针 。无返回NULL
{
OPR *headSave=oprHead;
while(headSave-next!=NULL)
{
if(headSave-next-cen==cen)
return headSave-next;
headSave=headSave-next;
}
return NULL;
}
void printfLog()//打印操作流水
{
OPR *headSave=oprHead;
int p1_take,p1_goAd,p2_take,p2_goAd,cen,p1TOp2,p2TOp1;
while(headSave-next!=NULL)
{
p1_take=headSave-next-p1_take;
p1_goAd=headSave-next-p1_goAd;
p2_take=headSave-next-p2_take;
p2_goAd=headSave-next-p2_goAd;
cen=headSave-next-cen;
if(p1_take0 || p1_goAd0)
p1TOp2=1;
else
p1TOp2=0;
if(p2_take0 || p2_goAd0)
p2TOp1=1;
else
p2TOp1=0;
printf("操作流水-:",cen);
printf("%s%s",p1TOp20?"从p1":"",p2TOp10?"从p2":"");
printf("%s%s",p1_goAd0?getName(p1_goAd):"",p1_goAd0?"下船":"");
printf("%s%s",p1_take0?getName(p1_take):"",p1_take0?"上船":"");
printf("%s%s",p2_goAd0?getName(p2_goAd):"",p2_goAd0?"下船":"");
printf("%s%s",p2_take0?getName(p2_take):"",p2_take0?"上船":"");
if(headSave-next-next!=NULL)
printf(" 。之后行驶方向:%s%s\n",p1TOp20?"p1-p2":"",p2TOp10?"p1-p2":"");
else
printf("\n");
headSave=headSave-next;
}
}
char *getName(int b)//获取对应名称
{
if(b==1000)
return "人";
else if(b==100)
return "狼";
else if(b==10)
return "羊";
else if(b==1)
return "菜";
return "";
}
int toShip(int *p1,int *p2,int *ship,bool f)//递归函数:上船人及任意一组合;lastTake:上一次承载物体,首次调用传0;f=0:p1-p2方向;1:反向 。返回状态,1:方案可行;0:方案不可行;
{
int take=-1,goAd,gdflag=1,cenSave;//take:上船物体 。goAd:下船物体 。gdflag:标识变量,p2判断能否直接下船,1能0不能
cenSave=cen;
while(1)
{
goAd=*ship-1000;
if(f==0)//准备p1往p2
{
if(take==-1)
take=getFist(*p1);
*p1-=take;
*p1 =goAd;
gdflag=1;//标识置1 , 等到p2首先尝试直接卸货
}
else//准备p2往p1
{
if(take==-1gdflag==0)
{
take=getFist(*p2);
printf("开始尝试替换货物:\n");
}
if(gdflag==1)//如果p2可以直接卸货
*p2 =goAd;
else//如果不能直接卸货,尝试带走一个同时卸货
{
*p2-=take;
*p2 =goAd;
}
}
printf("递归层级%d:假设%s从%s上船 。%s下船,%s方向行驶 。\n",cenSave,take0?getName(take):"无货物",f==0?"p1":"p2",goAd!=0?getName(goAd):"无货物",f==0?"p1往p2":"p2往p1");
if(beEaten(*p1,*p2))//如果发生被吃,假设失败 , 还原数据 , 选择下一假设
{
if(f==0)
{
*p1 =take;
*p1-=goAd;
}
else
{
if(gdflag==1)//p2点确定不能直接卸货 , 还原数据,标识置0
{
printf("----不能直接卸货 , 货物%s回到船上 。",getName(goAd));
*p2-=goAd;
gdflag=0;
continue;
}
else//不能直接卸货并尝试替换货物失败 , 选择下一个货物替换
{
*p2 =take;
*p2-=goAd;
}
}
if(take==1)
{
printf("本次靠岸无可行的装卸方案 , 返回层级%d!\n",cenSave-1);
return 0;
}
take=take/10;//尝试选择下一个货物
continue;
}
else
{
if(f==1gdflag==1)//p2直接卸货假设成立船清空
*ship=1000;
else
*ship=1000 take;//换货假设成立货物装船
if(*p1==0)//如果已经完全转移
{
printf("所有货物过河成功?。n");
return 1;
}
if(f==0)
addLog(take,goAd,0,0,cenSave);//生成流水日志
else
addLog(0,0,take,goAd,cenSave);//生成流水日志
if(toShip(p1,p2,ship,f==0?1:0))
{
return 1;
}
else//由于下级失败,本回合重新选择
{
gdflag=0;
continue;
}
}
}
}
int getFist(int pn)//获取物品组合中第一个
{
int i,count=0;
while(1)//上船物体从岸上第一个物体开始选择
{
if(pn=1)
break;
pn=pn/10;
count;
}
for(i=0;icount;i)
pn=pn*10;
return pn;
}
int beEaten(int p1,int p2)//检查是否发生被吃事件,发生返回1,未发生返回0
{
int ren=0;
if(p1==110ren==1)
printf("----河岸p1狼把羊吃了!重新选择\n");
if(p2==110ren==1)
printf("----河岸p2狼把羊吃了!重新选择\n");
if(p1==11ren==1)
printf("----河岸p1羊把菜吃了!重新选择\n");
if(p2==11ren==1)
printf("----河岸p2羊把菜吃了!重新选择\n");
return ren;
}
讲一下c语言中递归函数的使用方法递归函数有三点要求:
1,递归的终止点,即递归函数的出口
2 , 不断的递归调用自身
3,递归函数主体内容,即递归函数需要做的事情
ps:3一般可以放在2的前面或者后面 , 一般1放最前面 。另外,2和3可以根据不同的需要合并,比如 , 有时候递归函数的主体就是返回调用下层函数所得到的结果 。
具体例子如下:
void fun(int n)
{
if(n=0) return;//1 这是递归的终点,即出口
fun(n-1);//2、递归函数自身的调用
coutnendl;//3 递归函数的主体内容
}
2,3合并的情况
int fun(int n)
{
if(n=0) return 0;
return fun(n-1) fun(n-2);//2 3合并
}
c语言递归函数递归函数:
编程语言中,函数Func(Type a,……)直接或间接调用函数本身 , 则该函数称为递归函数 。递归函数不能定义为内联函数 。
在数学上,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A , 那么若对于A集合中的某一个值X0,其函数值f(x0)由f(f(x0))决定 , 那么就称f(x)为递归函数 。
函数介绍:
在数理逻辑和计算机科学中,递归函数或μ-递归函数是一类从自然数到自然数的函数 , 它是在某种直觉意义上是"可计算的"。事实上,在可计算性理论中证明了递归函数精确的是图灵机的可计算函数 。递归函数有关于原始递归函数 , 并且它们的归纳定义(见下)建造在原始递归函数之上 。但是,不是所有递归函数都是原始递归函数 — 最著名的这种函数是阿克曼函数 。
其他等价的函数类是λ-递归函数和马尔可夫算法可计算的函数 。
例子:
//代码1
void func()
{
//...
if(...)
func();
else
//...
}
条件:
一个含直接或间接调用本函数语句的函数被称之为递归函数,在上面的例子中能够看出,它必须满足以下两个条件:
1) 在每一次调用自己时,必须是(在某种意义上)更接近于解;
2) 必须有一个终止处理或计算的准则 。
梵塔的递归函数:
//C
void hanoi(int n,char x,char y,char z)
{
if(n==1)
move(x,1,z);
else
{
hanoi(n-1,x,z,y);
move(x,n,z);
hanoi(n-1,y,x,z);
}
}
【函数递归赶羊c语言 函数递归调用c语言】关于函数递归赶羊c语言和函数递归调用c语言的介绍到此就结束了 , 不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。

    推荐阅读