IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构之递归与栈的相关实现(C语言) -> 正文阅读

[数据结构与算法]数据结构之递归与栈的相关实现(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函数

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-15 15:50:18  更:2021-08-15 15:52:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:23:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码