`

递归与非递归之间的转化

阅读更多

在常规表达式求值中:

输入为四则运算表达式,仅由数字、+、-、*、/ 、(、) 组成,没有空格,要求求其值.

我们知道有运算等级,从左至右,括号里面的先运算,其次是* 、/,再是+、- ;

这样我们就可以用递归来表达这个式子了:

1.                         

 2.

          

 3.          

 

     这样就可以用递归来描述了

1. 

/**
求一个因子的值
*/
double factor_value(){
   double result = 0 ;
   char c = cin.peek();//从cin看一个字符,不取出
   if(c=='('){
        cin.get();
        result = expression_value() ;
        cin.get();
      }
    else{
        while(isdigit(c))//检查参数c是否为阿拉伯数字0到9
        {
            result = 10*result + c - '0' ;
            cin.get() ;
            c = cin.peek();
        }

    }
   return result ;
}

 

2.
/**
求一个项的值
*/
double term_value()
{
  double result = factor_value() ;//求第一个因子的值
  bool more = true ;
  while(more){
     char op = cin.peek() ;
     if(op=='*'||op=='/'){
         cin.get() ;
         int value = factor_value() ;
         if(op == '*') result*= value ;
         else  result /= value ;
      }
      else more = false ;
    }
    return result ;
}
 3.
/**
求一个表达式的值
*/
double expression_value(){
   double result = term_value() ;//求第一项的值
   bool more = true ;
    while(more){
     char op = cin.peek() ;
     if(op=='+'||op=='-'){
         cin.get() ;
         int value = term_value() ;
         if(op == '+') result+= value ;
         else  result -= value ;
      }
      else more = false ;
    }
    return result ;
}
  

4.

#include<iostream>
using namespace std ;
double factor_value();//因子
double term_value();//项
double expression_value();//表达式
int main()
{
cout << expression_value() << endl;
    return 0 ;
}

    总结下递归的优缺点:

    优点:直接、简捷、算法程序结构清晰、思路明了。

    缺点:递归的执行过程很让人头疼。

 

下面我们就用栈来替代上面的递归程序:

 首先理解栈的概念:栈是一种应用范围广泛的数据结构,适用于各种具有“后进先出”特性的问题。

 

 栈与过程调用:

  1.考虑下面三个过程:

     public void A1(){

     begin :

      ........    

      r: b();

     .........

      endl ;

     }

     public void A2(){

       begin :

      ........    

      t: c();

     .........

      endl ;

      }

      public void A3(){

           begin :

            ........    

           endl ;

      }

过程A1在其过程体的某一处调用过程A2,A2以在其过程体的某一处调用过程A3,A3不调用其他过程。

当过程A1执行到的r处时,它自己实际上被"挂起来,而被调用过程A2开始运行。一直等到A2执行完毕这后才返回过程A1的r1处继续执行A1剩下部分。 在过程A2的上述运行中,由于调用了A3,A2同样在t处"挂"起并一直等到A3执行结束后返回t1处才能继续执行后继语句。

     

 2.嵌套调用过程中调用关系

        

 3.相应工作栈的变化

    遇到一个过程调用便立刻将相应的返回位置(及其它有用的信息)进栈;每当一被调用过程执行结束时,工作栈栈顶元素下好是此过程的返回位置。

 就以上面的常规表达式为例:

        例: 1+(3-2)*4/2  

步骤       OPTR栈       OPND栈      输入字符      主要操作
 1           #                          1          PUSH(OPND,'1')
 2           #             1            +          PUSH(OPTR,'+')
 3           #+            1            (          PUSH(OPTR,'(')
 4           #+(           1            3          PUSH(OPND,'3')
 5           #+(           13           -          PUSH(OPTR,'-')
 6           #+(-          13           2          PUSH(OPND,'2')
 7           #+(-          132          )          operate('3','-','2')
 8           #+(           11                      POP(OPTR){消去一对括号}
 9           #+            11           *          PUSH(OPTR,'*')
 10          #+*           11           4          PUSH(OPND,'4')
 11          #+*           114          /          operate('1','*','4')
 12          #+            14                      PUSH(OPTR,'/')
 12          #+/           14           2          PUSH(OPND,'2')
 13          #+/           142          #          PUSH(OPND,'#')       
 14          #+/           142                     operate('4','/','2')
 15          #+            12                      operate('1','+','2')
 16          #               3                       return(GetTop(OPND)); 

 

4.为什么要学习递归与非递归的转换方法:

并不是每一门语言都支持递归的
有助于理解递归的本质
有助于理解栈,树等数据结构
一般来说,递归时间复杂度和对应的非递归差不多,但是递归的效率是相当低,它主要花费在反复的进栈出栈,各种中断等机制上,更有甚者,在递归求解过程中,某些解会重复的求好几次。

 

5.递归与非递归转换的原理
简单递归一般就是根据递归式来找出递推公式,即引入循环、递归调用树来模拟递归
复杂递归一般就是模拟系统处理递归的机制,使用栈或队列等数据结构保存回溯点来求解。

 

举个例子:在快速排序中,就可以清晰的理解其中的道理。

 我还是用Java还举这个例子吧,不用G++了

 1.用递归实现快速排序

 

package dsa;
/**
 * 快速排序
 * @author tanlvxu
 *
 */
public class Demo21 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		int a[]={4,3,2,5} ;
		new Demo21().qSort_Init(a, 0, 3) ;
		for(int i=0;i<=3;i++)
		System.out.print(a[i]) ;

	}
	public void swap(int a[],int low,int high)
	{
		int temp = a[low] ;
		a[low] = a[high] ;
		a[high] = temp ;
	}
	public int qSort(int a[],int low,int high)
	{
		int p = a[low] ;
		while(low<high)
		{
			while(low<high && a[high]>=p)
			{
				high-- ;
			}
			swap(a,low,high) ;
			while(low<high && a[high]<=p)
			{
				low++ ;
			} 
			swap(a,low,high) ;
		}
		
		return low ;
		
	}
	public void qSort_Init(int a[],int low,int high)
	{
		int p ;
		if(low<high)
		{
			p = qSort(a,low,high);
			qSort_Init(a,low,p-1);
			qSort_Init(a,p+1,high);
		}
	}

}

 2.用栈实现快速排序

 

package dsa;
/**
 * 用栈实现快速排序
 * @author tanlvxu
 *
 */
public class Demo22 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int a[]={4,3,2,5} ;
		new Demo22().qSort_Init(a, 0, 3) ;
		for(int i=0;i<=3;i++)
		System.out.print(a[i]) ;
	}
	public void swap(int a[],int low,int high)
	{
		int temp = a[low] ;
		a[low] = a[high] ;
		a[high] = temp ;
	}
	public int qSort(int a[],int low,int high)
	{
		int p = a[low] ;
		while(low<high)
		{
			while(low<high && a[high]>=p)
			{
				high-- ;
			}
			swap(a,low,high) ;
			while(low<high && a[high]<=p)
			{
				low++ ;
			} 
			swap(a,low,high) ;
		}
		
		return low ;
		
	}
    public void qSort_Init(int a[],int low,int high)
    {
    	int m[] = new int[100] ;
    	int n[] = new int[100] ;
    	int cp,p,sublow,subhigh ;
    	/*
    	 * 初始化栈和栈顶指针
    	 */
    	m[0] = low ;
    	n[0] = high ;
    	cp = 0 ;
    	while(cp>=0){
    		sublow = m[cp] ;
    		subhigh = n[cp] ;
    		cp -- ;
    		if(sublow<subhigh){
    			 p = qSort(a, sublow, subhigh) ;
    			 cp ++ ;
    			 m[cp] = sublow ;
    			 n[cp] = p-1 ;
    			 cp++ ;
    			 m[cp] = p + 1;
    			n[cp] = subhigh;
    		}
    		
    		
    	}
    	
    	
    }
}

 

  • 大小: 4.4 KB
  • 大小: 3.9 KB
  • 大小: 5.5 KB
  • 大小: 9.2 KB
  • 大小: 1.3 KB
分享到:
评论

相关推荐

    递归算法与非递归转化

    递归算法与非递归转化 递归算法是把问题转化为规模缩小了的同类问题的子问题,然后递归调用函数(或过程)来表示问题的解。递归的效率一般不高,但是递归比较符合人类的思维方式。一般而言非递归算法更有效;但很多...

    快速排序算法设计与分析总结 二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现

    快速排序算法设计与分析总结 二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现 二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现,应包含建树的实现 实现树与...

    如何用栈实现递归与非递归的转换

    "递归与非递归转换的基础知识" 一、为什么要学习递归与非递归的转换的实现方法? 学习递归与非递归的转换是非常重要的,因为它可以帮助我们更好地理解递归和栈这两个重要的数据结构。首先,不是所有的编程语言都...

    二叉树与树的转换前序、后序的递归、非递归算法,层次序的非递归算法的实现,应包含建树的实现。

    根据给定文件的信息,本文将详细介绍二叉树与树之间的转换方法,并且深入探讨树的前序、中序、后序遍历递归与非递归实现方式,以及层次遍历的非递归算法实现。 ### 二叉树与树的转换 在计算机科学中,树是一种常用...

    ackermann函数的递归实现和非递归实现

    非递归实现的基本思想是将递归调用转化为循环,并使用数据结构(如堆栈)存储中间结果,避免了递归带来的调用栈溢出问题。 非递归实现的步骤大致如下: 1. 初始化一个堆栈,用于保存待处理的阿克曼函数参数对`(m, ...

    递归算法到非递归算法的转换.ppt

    本章将探讨如何将递归算法转换为非递归算法。 首先,我们要了解递归的定义。递归发生在一个过程或函数在定义中调用自身,这被称为直接递归。如果一个过程调用另一个,而后者又调用前者,那么这是间接递归。例如,...

    二叉树中前后序层次的递归、非递归算法

    20二叉树的中序、前序、后序的递归、非递归遍历算法,层次序的非递归遍历算法的实现,应包含建树的实现。(2 人) 要求: 树与二叉树的转换的实现。以及树的前序、后序的递归、非递归遍历算法,层次序的非递归遍历...

    快速排序的非递归实现

    非递归实现快速排序的关键在于使用栈来模拟递归调用的过程。在递归版本中,我们首先选择一个基准元素(pivot),然后将数组分为两部分:小于基准的元素和大于或等于基准的元素。接着对这两部分分别进行递归排序。非...

    递归算法转为非递归算法

    递归算法转为非递归算法。方法、过程,用栈的原理

    5!递归算法和非递归算法

    在计算机科学与编程领域中,递归算法与非递归算法是两种非常重要的计算方法。本文将详细介绍这两种算法的特点、应用场景以及如何实现它们,特别针对初学者及面试准备者。 #### 递归算法 递归算法是一种直接或间接...

    编译原理非递归预测分析

    与递归下降解析器通过函数调用实现语法分析不同,非递归预测分析使用栈来存储符号,并基于当前输入符号和栈顶符号的状态来决定下一步的操作。这种方法也被称为LR(Left-to-Right, Rightmost-derivation)分析,因为...

    阿克曼函数非递归实现

    通过以上分析,我们可以看到,阿克曼函数的非递归实现主要涉及堆栈操作、递归转换以及对计算复杂性的理解。这个话题对于学习数据结构和算法的学生来说,是一个挑战性的实践项目,有助于提升他们的编程技能和对复杂...

    递归算法与非递归算法的转换文.pdf

    **递归算法与非递归算法的转换** 递归算法是一种强大的编程技术,它通过将问题分解成规模更小的相同问题来解决复杂问题。在递归算法中,函数或过程会直接或间接地调用自身,直到遇到一个基本的终止条件,即递归出口...

    浅谈递归机制和非递归转换.txt

    根据给定文件的信息,我们可以提炼出递归机制与非递归转换的相关知识点: ### 递归机制 #### 定义 ...通过对递归原理的理解和掌握,以及对递归与非递归之间的转换,可以帮助我们更好地解决复杂问题。

    数据结构:栈的应用-递归函数转非递归函数

    在计算机科学中,数据结构是组织和管理数据的方式,它直接影响到程序的效率和性能。栈是一种特殊的数据结构,...理解并掌握如何将递归转化为非递归,不仅可以提升代码质量,也是成长为一名优秀程序员的关键技能之一。

    树的遍历,递归和非递归实现方式,工程源码

    本压缩包包含的是关于树的遍历,特别是递归和非递归实现方式的工程源码,这些代码基于C++语言,存放在Dep工程文件夹中。 首先,我们要理解什么是树的遍历。树遍历是指按照特定顺序访问树的所有节点。通常,有三种...

    MFC先序序列建树及递归非递归遍历

    本话题聚焦于使用MFC(Microsoft Foundation Classes)库在C++环境中实现树的各种遍历算法,包括先序、中序和后序遍历,既可以通过递归方式,也可以采用非递归方法。 首先,我们来理解树的基本概念。树由节点和边...

    汉诺塔的非递归实现,c++

    非递归算法通常通过使用数据结构(如栈)来模拟递归过程,从而避免了递归调用带来的额外开销。 首先,我们需要创建一个栈来存储盘子的状态。栈将用于保存每个盘子的移动顺序,以便在适当的时候回溯。在C++中,可以...

    hanoi(汉诺塔)问题的非递归实现

    贺存薪提出的非递归算法的核心是通过观察递归算法中的移动规律,并将其转化为一系列确定性的操作。通过这种方式,可以有效地避免递归调用所带来的额外开销,从而提高算法的整体效率。 ##### C++实现 非递归算法的...

Global site tag (gtag.js) - Google Analytics