学习日志---递归、非递归,迷宫问题

递归算法的设计方法:

适宜于用递归算法求解的问题的充分必要条件是:

(1)问题具有某种可借用的类同自身的子问题描述的性质
   (2)某一有限步的子问题(也称作本原问题)有直接的解存在。
当一个问题存在上述两个基本要素时,设计该问题的递归算法的方法是:
   (1)把对原问题的求解表示成对子问题求解的形式。
   (2)设计递归出口。

阶乘:

import java.util.Scanner;

public class JieChengDemo {
    public static long jieCheng(int num)
    {
        if(num==1)
        {
            return 1;
        }
        else
        {
            return num*jieCheng(num-1); //递归调用
        }
    }  
    public static void main(String[] args) {
        
        int num;
        long result;
        Scanner in = new Scanner(System.in);
        System.out.println("请输入一个正整数:");
        num = in.nextInt();
        result = JieChengDemo.jieCheng(num);
        System.out.println(num+"的阶乘是:"+result);    
    }
}

折半查找递归实现:

import java.util.Scanner;

public class BinarySearch {
    
    public static boolean bSearch(int[] arr,int des,int low,int high)
    {
        int mid; //中间的下标
        if(low > high)
        {
            return false;
        }
        mid = (low+high)/2;
        if(des == arr[mid])
        {
            return true;
        }
        else if(des < arr[mid])
        {
           return bSearch(arr,des,low,mid-1); //递归调用    
        }
        else
        {
           return bSearch(arr,des,mid+1,high);    
        }
    }
         
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int[] arr = {1,6,11,17,23,45,56,76,87,93};
        int des;
        Scanner in = new Scanner(System.in);
        System.out.println("请输入一个正整数(0-99):");
        des = in.nextInt();
        if(BinarySearch.bSearch(arr, des, 0, arr.length-1))
        {
            System.out.println(des+"在数组当中!");
        }
        else
        {
            System.out.println(des+"不在数组当中!");
        }
    }

}
斐波纳挈数列:
public class Bolienac {
  
    //获得波列那契数列第N项的值
    public static int getNums(int n)
    {
        if(n==1||n==2)
        {
            return 1;
        }
        else
        {
            return getNums(n-1)+getNums(n-2);
        }
    }
    
    
    public static void main(String[] args)
    {
        //1,1,2,3,5,8,13
        int n=7;
        int result=0;
        for(int i=n;i>=1;i--)
        {
            result+=Bolienac.getNums(i);
        }
        System.out.println("波列那契数列的前"+n+"项之和是:"+result);
    }
    
}

求最大公约数:

public class GcbNumber {
    
    //求最大公约数的递归算法。
    public static int gcb(int bigNum,int smallNum)
    {
        if(bigNum<0||smallNum<0)
        {
            return -1; //表示没有找到最大公约数。
        }
        if(smallNum==0)
        {
            return bigNum;
        }
        if(bigNum < smallNum)
        {
            //这里也是函数套用的好方法
            return gcb(smallNum,bigNum);
        }
        else
        {
           //这里是传进去大数除以小数取余数和小数
           return gcb(smallNum,bigNum%smallNum);    
        }
    }
    
    
    public static void main(String[] args)
    {
         int smallNum = 30;
         int bigNum = 25;
         int result = GcbNumber.gcb(bigNum, smallNum);
         if(result!=-1)
         {
             System.out.println(bigNum+"和"+smallNum+"的最大公约数是:"+result);
         }
        
    }
}

递归过程和运行时栈:

递归函数的执行过程具有三个特点:
    (1)函数名相同;
    (2)不断地自调用;
    (3)最后被调用的函数要最先被返回。
 系统用于保存递归函数调用信息的堆栈称作运行时栈。
 每一层递归调用所需保存的信息构成运行时栈的一个工作记录  
 栈顶的工作记录保存的是当前调用函数的信息,所以栈顶的工作记录也称为活动记录。

递归转为非递归算法:

一般来说,如下两种情况的递归算法可转化为非递归算法:
(1)存在不借助堆栈的循环结构的非递归算法,如阶乘计算问题、斐波那契数列的计算问题、折半查找问题等
(2)存在借助堆栈的循环结构的非递归算法。所有递归算法都可以借助堆栈转换成循环结构的非递归算法。

回溯法:也是递归算法中一个经典思想

回溯法的基本思想是:对一个包括有很多结点,每个结点有若干个搜索分支的问题,把原问题分解为对若干个子问题求解的算法。当搜索到某个结点、发现无法再继续搜索下去时,就让搜索过程回溯(即退回)到该结点的前一结点,继续搜索这个结点的其他尚未搜索过的分支;如果发现这个结点也无法再继续搜索下去时,就让搜索过程回溯到这个结点的前一结点继续这样的搜索过程;这样的搜索过程一直进行到搜索到问题的解或搜索完了全部可搜索分支没有解存在为止。

迷宫问题:

public class MyMaze {
    
    private static int startPosI;//入口的i下标
    private static int startPosJ;//入口的j下标
    private static int endPosI;//出口的i下标
    private static int endPosJ;//出口的j下标
    
    //设置迷宫入口的坐标
    public void setStart(int startPosI,int startPosJ)
    {
       MyMaze.startPosI = startPosI;
       MyMaze.startPosJ = startPosJ;
    }
    
    //设置迷宫出口的坐标
    public void setEnd(int endPosI,int endPosJ)
    {
       MyMaze.endPosI = endPosI;
       MyMaze.endPosJ = endPosJ;
    }
    
    //迷宫搜索通路的算法
    /*  cell:迷宫地图
     *  i: 入口的i坐标
     *  j: 入口的j坐标
     **/
    public static void visited(int[][] cell,int i,int j)
    {
        cell[i][j]=1;
        
        if(i==endPosI&&j==endPosJ) //找到了出口
        {
            System.out.println("找到一条通路:");
            for(int m=0;m<cell.length;m++)
            {
                for(int n=0;n<cell[0].length;n++)
                {
                    if(cell[m][n]==2)
                    {
                        System.out.print("2");
                    }
                    else if(cell[m][n]==1)
                    {
                        System.out.print("*");    
                    }
                    else
                    {
                        System.out.print(" ");
                    }
                }
                System.out.println();
            }
        }else{
             //向左边寻找通路
            if(cell[i][j-1]==0)
            {
                visited(cell,i,j-1);
            }
            //向右边寻找通路
            if(cell[i][j+1]==0)
            {
               visited(cell,i,j+1);
            }
            //向上寻找通路
            if(cell[i-1][j]==0)
            {
               visited(cell,i-1,j);
            }
            //向下寻找通路
            if(cell[i+1][j]==0)
            {
                visited(cell,i+1,j);
            }     
        }
       
        //下面的变0很关键,这一点很关键,是回溯法的本质,如果以上路都走不通,则把原来的路还原,上一层的函数
          调用结束,上一层的函数则去寻找其他的路。每一次对的寻找都是不会把其置为0,一直到
          最后一步打印完,之后
          
        cell[i][j]=0;
    }
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
       
        //初始化一个迷宫地图
        int[][] maze={
                {2,2,2,2,2,2,2,2,2},
                {2,0,0,0,0,0,0,0,2}, 
                {2,0,2,2,0,2,2,0,2}, 
                {2,0,2,0,0,2,0,0,2},
                {2,0,2,0,2,0,2,0,2}, 
                {2,0,0,0,0,0,2,0,2}, 
                {2,2,0,2,2,0,2,2,2}, 
                {2,0,0,0,0,0,0,0,2}, 
                {2,2,2,2,2,2,2,2,2}
        };
        
        MyMaze cell = new MyMaze();
        cell.setStart(1, 1);//设置迷宫的入口坐标
        cell.setEnd(7, 7);//设置迷宫的出口坐标
        cell.visited(maze, 1, 1);
    }

}
时间: 2024-10-06 03:34:02

学习日志---递归、非递归,迷宫问题的相关文章

快速排序递归非递归队列堆栈实现

递归实现 #include<iostream> using namespace std; template <class T> void QuickSort(T A[],int left,int right) { if(left<right) { int i=left; int j=right+1; do { do i++;while(A[i]<A[left]); do j--;while(A[j]>A[left]); if(i<j) Swap(A[i],A

二叉树总结—建树和4种遍历方式(递归&amp;&amp;非递归)

今天总结一下二叉树,要考离散了,求不挂!二叉树最重要的就是 建立.4种遍历方式,简单应用,如何判断两颗二叉树是否相似 二叉树分为 :1.完全二叉树  2.满二叉树 结构性质: 1).满二叉树 高度为h ,节点数则为 2^h - 1,且叶子节点全在最下层,且叶子节点数为2^(n-1)个{n代表二叉树层数,也叫深度} 2).n个节点的 完全二叉树 深度为 int(log2n)(以2为底n的对数)+ 1: 3).非空二叉树 叶子节点个数==双分支节点数+1 4).非空二叉树 某节点编号 n  若有左孩

【算法拾遗】二分查找递归非递归实现

转载请注明出处:http://blog.csdn.net/ns_code/article/details/33747953 本篇博文没太多要说的,二分查找很简单,也是常见常考的查找算法,以下是递归非递归的实现. 非递归实现: /* 非递归实现,返回对应的序号 */ int BinarySearch(int *arr,int len,int key) { if(arr==NULL || len<1) return -1; int low = 0; int high = len-1; while(l

2013-03-17---二叉树递归,非递归实现(附代码)深度,叶子节点数量,逐行打印二叉树

昨天晚上没有发文章,说来话长啊,昨天不知道是csdn的问题,还是我的问题,我访问了半天,访问不上网站啊,后来12点多了,就睡了.上一篇文章说到了二叉树的先序,中序,后序遍历问题,这次还是说的简单的一点,说计算二叉树的深度,和叶子节点数量 int ceng(Node *pRoot) //计算层数,递归实现 { int left = 0; int right = 0; int res = 0; if (pRoot == NULL) { return 0; } if (pRoot->pLeft !=

二叉树基础(创建方法,遍历方法(前序/中序/后序/层序、递归/非递归)

二叉树的创建及遍历是很多二叉树问题的基础,递归遍历逻辑清晰,代码简约漂亮,然则效率低下(所有递归方案的通病,非不得已不用递归): 非递归遍历高效,却不是能信手写出来的,特别是后续非递归遍历,相信很多资深码工也有这样的经历: 5年前学习了二叉树的非递归遍历,一个月前复习了并达到能熟练写出的程度,在不参考任何资料的情况下,今天却怎样也写不出来. 如果你也有过这种经历,恭喜你,这说明你是一个正常人…… 另一方面市面上有些国人写的教材,各种语法.逻辑错误层出不起,不知祸害了多少未来的码工,深感痛心. 印

二叉树——前序遍历、中序遍历、后序遍历、层序遍历详解(递归非递归)

前言 前面介绍了二叉排序树的构造和基本方法的实现.但是排序遍历也是比较重要的一环.所以笔者将前中后序.和层序遍历梳理一遍. 了解树的遍历,需要具有的只是储备有队列,递归,和栈.这里笔者都有进行过详细介绍,可以关注笔者数据结构与算法专栏.持续分享,共同学习. 层序遍历 层序遍历.听名字也知道是按层遍历.我们知道一个节点有左右节点.而每一层一层的遍历都和左右节点有着很大的关系.也就是我们选用的数据结构不能一股脑的往一个方向钻,而左右应该均衡考虑.这样我们就选用队列来实现. 对于队列,现进先出.从根节

作业 树和森林 遍历(递归/非递归先序,递归/非递归后序,递归层次)

1 #include <iostream> 2 #include"queue.h"//之前写的类 3 #include"stack.h" //之前写的类 4 using namespace std; 5 6 template <class T> 7 class Tree; 8 9 //======================================== 10 // 树节点类声明 11 template <class T>

二叉树的前序/中序/后续遍历(递归+非递归)

这几日又把二叉树的递归写了一遍,原来是用C写的,自己写了一个栈,这一次直接用的C++,使用了自带的栈结构.代码如下: 1 /************************************************************************* 2 > Author: Yves 3 > E-mail: [email protected] 4 > File Name: BiTreeNew.cpp 5 > Description: ... 6 > Cre

hdu 4850 字符串构造---欧拉回路构造序列 递归+非递归实现

http://acm.hdu.edu.cn/showproblem.php?pid=4850 题意:构造长度为n的字符序列,使得>=4的子串只出现一次 其实最长只能构造出来26^4+4-1= 456979 的序列,大于该数的都是不可能的.构造方法,就是那种欧拉回路的序列,此题DFS会爆栈,手动扩展栈也可以AC...... 递归形式的开始WA了,没有细调就换非递归了,后来又想了想,虽然自己电脑上运行不了,但是先把长度按小的来,然后调试代码,然后在扩大,AC了,当时错在MOD,递归的MOD应该是26

2015-03-15---二叉树递归(非递归)实现先序、中序、后序遍历(附代码)

今天说好的不碰代码的,后来还是没忍住,学了学数据结构和算法,就先讲讲先序中序和后序遍历吧,我还写了代码,一套递归方式实现遍历二叉树,还有两套非递归方式遍历二叉树, 从简单的开始,因为二叉树的所有操作都是要求在能够遍历的基础上啊. 学过数据结构的肯定都明白遍历顺序, 先序遍历就是先自己,然后左子树,然后右子树, 中序遍历就是先左子树,然后自己,然后右子树 后序遍历就是先左子树,然后右子树,然后自己 比如上图这个很简单的二叉树: 先序遍历:1 2 4 5 3 6 7 中序遍历:4 2 5 1 6 3