ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:23.70KB ,
资源ID:18997373      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/18997373.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(如何用栈实现递归与非递归的转换Word文件下载.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

如何用栈实现递归与非递归的转换Word文件下载.docx

1、 /* 根指针进栈 */ while(!stackempty(S) while(gettop(S,p)&p) /* 向左走到尽头 */ visit(p); /* 每向前走一步都访问当前结点 */ push(S,p-pop(S,p);if(!stackempty(S) /* 向右走一步 */ 2)中序遍历 a)递归方式 1f2a39cc2dvoid inorder_recursive(Bitree T) /* 中序遍历二叉树的递归算法 */ inorder_recursive(T-1f2a39cc2dvoid inorder_nonrecursive(Bitree T) /* 初始化栈 */ p

2、ush(S, T); /* 根指针入栈 */ while (!while (gettop(S, p) & p) /* 向左走到尽头 */ push(S, p-pop(S, p); /* 空指针退栈 */ if (! /* 向右走一步 */ 3)后序遍历 1f2a39cc2dvoid postorder_recursive(Bitree T) /* 中序遍历二叉树的递归算法 */ if (T) postorder_recursive(T- visit(T); 1f2a39cc2dtypedef struct BTNode* ptr;enum 0,1,2 mark; PMType; /* 有mar

3、k域的结点指针类型 */ void postorder_nonrecursive(BiTree T) /* 后续遍历二叉树的非递归算法 */ PMType a; /* S的元素为PMType类型 */ push (S,T,0); /* 根结点入栈 */ pop(S,a);switch(a.mark) case 0:push(S,a.ptr,1); /* 修改mark域 */ if(a.ptr-lchild)push(S,a.ptr-lchild,0);break;case 1:push(S,a.ptr,2);rchild)rchild,0);case 2:visit(a.ptr); /* 访问

4、结点 */ 4)如何实现递归与非递归的转换 通常,一个函数在调用另一个函数之前,要作如下的事情:a)将实在参数,返回地址等信息传递 给被调用函数保存; b)为被调用函数的局部变量分配存储区;c)将控制转移到被调函数的入口. 从被调用函数返回调用函数之前,也要做三件事情:a)保存被调函数的计算结果;b)释放被调 函数的数据区;c)依照被调函数保存的返回地址将控制转移到调用函数. 所有的这些,不论是变量还是地址,本质上来说都是数据,都是保存在系统所分配的栈中的. ok,到这里已经解决了第一个问题:递归调用时数据都是保存在栈中的,有多少个数据需要保存 就要设置多少个栈,而且最重要的一点是:控制所有这

5、些栈的栈顶指针都是相同的,否则无法实现 同步. 下面来解决第二个问题:在非递归中,程序如何知道到底要转移到哪个部分继续执行?回到上 面说的树的三种遍历方式,抽象出来只有三种操作:访问当前结点,访问左子树,访问右子树.这三 种操作的顺序不同,遍历方式也不同.如果我们再抽象一点,对这三种操作再进行一个概括,可以 得到:a)访问当前结点:对目前的数据进行一些处理;b)访问左子树:变换当前的数据以进行下一次 处理;c)访问右子树:再次变换当前的数据以进行下一次处理(与访问左子树所不同的方式). 下面以先序遍历来说明: visit(T)这个操作就是对当前数据进行的处理, preorder_recursi

6、ve(T-lchild)就是把当前 数据变换为它的左子树,访问右子树的操作可以同样理解了. 现在回到我们提出的第二个问题:如何确定转移到哪里继续执行?关键在于一下三个地方:a) 确定对当前数据的访问顺序,简单一点说就是确定这个递归程序可以转换为哪种方式遍历的树结 构;b)确定这个递归函数转换为递归调用树时的分支是如何划分的,即确定什么是这个递归调用 树的左子树和右子树c)确定这个递归调用树何时返回,即确定什么结点是这个递归调用树的 叶子结点. 三.三个例子 好了上面的理论知识已经足够了,下面让我们看看几个例子,结合例子加深我们对问题的认识 .即使上面的理论你没有完全明白,不要气馁,对事物的认识

7、总是曲折的,多看多想你一定可以明 白(事实上我也是花了两个星期的时间才弄得比较明白得). 1)例子一:1f2a39cc2df(n) = n + ; (n = 2);这个例子相对简单一些,递归程序如下:int f_recursive(int n) int u1, u2, f;if (n 2)f = n + 1;else u1 = f_recursive(int)(n/2);u2 = f_recursive(int)(n/4);f = u1 * u2;return f; 下面按照我们上面说的,确定好递归调用树的结构,这一步是最重要的.首先,什么是叶子结点 ,我们看到当n = 0) switch(f

8、lagcp) /* 访问的是根结点 */ if (stackcp = 2) /* 左子树入栈 */ flagcp = 1; /* 修改标志域 */ cp+;stackcp = (int)(stackcp - 1 / 2);flagcp = 0; else /* 否则为叶子结点 */ stackcp += 1;flagcp = 2; /* 访问的是左子树 */ = 2) /* 右子树入栈 */ cp += 2;stackcp = (int)(stackcp - 2 / 4); /* */ if (flagcp - 1 = 2) /* 当前是右子树吗? */ /* 如果是右子树, 那么对某一棵子树

9、的后序遍历已经 * 结束,接下来就是对这棵子树的根结点的访问 */ stackcp - 2 = stackcp * stackcp - 1;flagcp - 2 = 2;cp = cp - 2; else/* 否则退回到后序遍历的上一个结点 */ cp-;return stack0; 算法分析:a)flag只有三个可能值:0表示第一次访问该结点,1表示访问的是左子树,2表示 已经结束了对某一棵子树的访问,可能当前结点是这棵子树的右子树,也可能是叶子结点.b)每 遍历到某个结点的时候,如果这个结点满足叶子结点的条件,那么把它的flag域设为2;否则根据 访问的是根结点,左子树或是右子树来设置fl

10、ag域,以便决定下一次访问该节点时的程序转向. 2)例子二 快速排序算法 递归算法如下:1f2a39cc2dvoid swap(int array, int low, int high) int temp;temp = arraylow;arraylow = arrayhigh;arrayhigh = temp;int partition(int array, int low, int high) int p;p = arraylow;while (low = p)high-;swap(array,low,high); arraylow low+;return low;void qsort_r

11、ecursive(int array, int low, int high) if(low p = partition(array, low, high);qsort_recursive(array, low, p - 1);qsort_recursive(array, p + 1, high); 需要说明一下快速排序的算法: partition函数根据数组中的某一个数把数组划分为两个部分, 左边的部分均不大于这个数,右边的数均不小于这个数,然后再对左右两边的数组再进行划分.这 里我们专注于递归与非递归的转换,partition函数在非递归函数中同样的可以调用(其实 partition函数就是

12、对当前结点的访问). 再次进行递归调用树和栈的分析: 递归调用树:a)对当前结点的访问是调用partition函数;b)左子树:c)右子树:d)叶子结点:当low high时;e)可以看出这是一个先序调用的二叉树 栈:要保存的数据是两个表示范围的坐标. 1f2a39cc2dvoid qsort_nonrecursive(int array, int low, int high) int m50, n50, cp, p;m0 = low;n0 = high;while (mcp 0) /* 压栈, 直到m1cp = 0 */ while (n1cp /* 压栈, 直到n1cp = 0 */ m1

13、cp = m1cp - 1;n1cp = n1cp - 1 - 1;/* 计算akm(m - 1, 1),当n = 0时 */ m1cp = m1cp - 1;n1cp = 1;/* 改栈顶为akm(m - 1, n + 1),当m = 0时 */ n1cp = n1cp + 1 + 1; while (cp 0 | m1cp 0);return n10 + 1;0351fd7499三.递归程序的分类及用途 递归程序分为两类:尾部递归和非尾部递归.上面提到的几个例子都是非尾部递归,在一个选择分支中有至少 一个的递归调用.相对而言,尾部递归就容易很多了,因为与非尾部递归相比,每个选择分支只有一个

14、递归调用, 我们在解决的时候就不需要使用到栈,只要循环和设置好循环体就可以了.下面再举几个尾部递归的例子吧,比较 简单我就不多说什么了. 1)例子一 code:785fd53e3eg(m, n) = 0 (m = 0, n = 0) = g(m - 1, 2n) + n; (m 0, n = 0)/code:785fd53e3e a)递归程序 785fd53e3eint g_recursive(int m, int n) if (m = 0 & n = 0)return 0;return (g_recurse(m - 1, 2*n) + n);785fd53e3e b)非递归程序 785fd53e3eint g_nonrecursive(int m, int n) for (p = 0; m 0 &= 0; m-, n *= 2)p += n;return p;/code

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1