数据结构之递归与栈的相关实现(C语言)

参考:1.网课:数据结构与算法基础(青岛大学-王卓)
2.教材:数据结构(c语言版)第二版,严蔚敏,李冬梅等著

非科班自学,如有错误望不吝赐教。

递归与栈

0.递归的定义

简单来说,递归就是自己调用自己,然后一层一层的返回。

函数可以调用自己
注意要设置停止条件

1.递归的过程,与栈的关系

栈与递归的关系,函数的递归调用和普通函数调用是一样的。当程序执行到某个函数时,将这个函数进行入栈操作,在入栈之前,通常需要完成三件事。

1、将所有的实参、返回地址等信息传递给被调函数保存。

2、为被调函数的局部变量分配存储区。

3、将控制转移到北调函数入口。

当一个函数完成之后会进行出栈操作,出栈之前同样要完成三件事。

1、保存被调函数的计算结果。

2、释放被调函数的数据区。

3、依照被调函数保存的返回地址将控制转移到调用函数。

上述操作必须通过栈来实现,即将整个程序的运行空间安排在一个栈中。每当运行一个函数时,就在栈顶分配空间,函数退出后,释放这块空间。所以当前运行的函数一定在栈顶。

(个人理解)
调用:就是把参数依次入栈
回退:把参数(对应的值)依次出栈

比如:
在这里插入图片描述

计算过程
依次将8,4,2,1,0入栈;
再将0对应的1,1对应的1F(0),…,8对应的8F(4)出栈

2.Ackerman函数

递归方法

#include <stdio.h>

int Ack(int m,int n)
{
  if(n<0||m<0){
      return 0;
  }
  else if(m==0){
      return n+1;
  } 
  else if(n==0){
      return Ack(m-1,1);
  }
  else
  return Ack(m-1,Ack(m,n-1));
}

int main(){
    int m=4,n=3;
    printf("%d",Ack(m,n));
}

非递归方法:

#include "stdio.h"
#include <stdlib.h>
 
typedef int DataType;
typedef struct node
{
	DataType m, n;
	struct node* next;
} LinkStack;//每个结点由数据域m和n,以及指针域next构成
 
void Show(LinkStack* p)
{
	printf("m:%d    n:%d\n", p->m, p->n);
}//打印当前节点的m和n值
 
DataType Akm(DataType m, DataType n)
{
        printf("以下模拟进出栈过程:");
	LinkStack* Top = (LinkStack*)malloc(sizeof(LinkStack));
	Top->m = m; 
	Top->n = n;
	Top->next = NULL;//初始化链栈
	Show(Top);
	DataType result = 0;
	while (Top != NULL)
	{
		//akm(m,n)=n+1,if m=0 
		if (Top->m == 0 && Top->n >= 0)
		{
			DataType x = Top->n + 1;
			while (Top != NULL && Top->n >= 0)//把到(0,n)上的结点全部释放掉
			{
				//出栈
				LinkStack* p = Top;
				Top = Top->next;
				free(p);
				printf("pop\n");
			}
			if (Top == NULL)  //最终结果
			{
				result = x;
				break;
			} 
			else if (Top->n < 0)//把中间结果入栈(替换原来的-1)
			{
				Top->n = x;
			}
		} 
		//akm(m,n)=akm(m-1,1),if m>0&&n=0 将m-1和1入栈
		else if (Top->m > 0 && Top->n == 0)
		{
			LinkStack* p = (LinkStack*)malloc(sizeof(LinkStack));
			p->m = Top->m - 1;
			p->n = 1;
			p->next = Top;
			Top = p;
			Show(Top);
		}
		//akm(m,n)=akm(m-1,akm(m,n-1)),if m>0&&n>0 先将m-1和-1入栈再将m和n-1入栈 ,接下来是计算akm(m,n-1)了
		else if (Top->m > 0 && Top->n > 0)
		{
			LinkStack* p = (LinkStack*)malloc(sizeof(LinkStack));
			LinkStack* q = (LinkStack*)malloc(sizeof(LinkStack));
			p->m = Top->m - 1;
			p->n = -1;
			q->m = Top->m;
			q->n = Top->n - 1;
			p->next = Top;
			Top = p;
			Show(Top);
			q->next = Top;
			Top = q;
			Show(Top);
		}
	}
	return result;
}
 
void main()
{	
    int m,n;
    scanf("%d,%d",&m,&n);
    if(m<0 ||n<0) return 0;
	DataType r = Akm(m, n);
	printf("结果为:%d\n", r);
}

这篇博客讲的很详细:如何使用栈非递归地求解Ackerman函数

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值