java四则运算(递归的思想)
- 格式:docx
- 大小:18.71 KB
- 文档页数:7
java 递归算法递归算法是一种编程技术,它使用一种叫做递归的迭代方法,可以解决复杂的问题。
递归算法指的是一种把一个大问题分解为一系列规模较小的子问题来解决的方法。
当容易解决规模较小的子问题时,可以递归地解决规模较大的问题,而无需编写代码。
一般来说,递归算法通过迭代(不断重新评估并重新求解问题)来实现,而无需编写大型程序分支来处理不同输入,只需要利用一个或几个函数就可以处理对问题的不同情况。
递归算法在计算机科学的应用领域非常广泛,它被广泛应用于解决数据结构、搜索算法以及逻辑程序等复杂的问题。
例如,一个树形结构的搜索算法依赖于递归算法来查找相应的结果,从而给出一个实用的解决方案。
本文将就递归算法作一个较为全面的介绍,重点介绍它在 Java 言中的实现。
首先,让我们来了解一下 Java言本身是如何实现递归算法的,即通过何种方式来实现递归的目的。
其核心思想是,一个函数的递归调用是指调用该函数的体内有一个或多个函数调用语句,其中被调用的函数可以是它自身,也可以是另一个函数。
为了实现递归调用,Java 言中提供了一个特殊的语句称为递归函数调用语句(recursive call),可以让一个函数调用它自身。
为了实现递归算法,必须要具备以下三个条件:1.本情形:一个函数在某些情况下不再调用自身,而是直接返回结果,称为基本情形。
2. 不断抽象:对每个问题的解决,都将它抽象成一个规模更小的子问题,这样递归地解决问题才有可能。
3.用自身:在子问题解决完毕后,再调用自身,也就是说调用函数的体内有一个或多个函数调用语句,其中被调用的函数可以是它自身。
接下来,让我们来看一个实际的实现案例,比如说,在 java言中实现一个求阶乘的递归算法。
在 Java言中,可以使用递归函数调用语句(recursive call)来实现递归算法。
以求阶乘的算法为例,其实现代码如下:public static long factorial(int n) {if (n <= 1) {return 1;}return n * factorial(n - 1);}上面的代码中,n 代表要求阶乘的数,此函数调用自身来实现求解,基本情形是当 n 为 1不再调用自身而是直接返回 1,当 n于 1,将 n阶乘计算表示为 n * (n - 1)阶乘的乘积,直到达到基本情形,最终求出阶乘的值。
递归算法java递归算法是一种在编程中常用的算法,它的思想是将一个问题分解成更小的子问题,并通过递归调用自身来解决这些子问题。
在Java编程中,递归算法常用于解决树形结构、图形结构等复杂数据结构的问题。
递归算法的基本原理是将一个大问题分解成若干个小问题,然后通过逐步解决这些小问题来达到解决大问题的目的。
在Java编程中,递归算法通常使用函数或方法来实现。
具体实现过程如下:1. 定义递归函数或方法:首先需要定义一个能够接受参数并返回值的函数或方法。
该函数或方法需要能够判断何时停止递归,并且需要能够处理每个子问题。
2. 设计停止条件:在定义函数或方法时,需要设定一个停止条件。
当满足该条件时,函数或方法将不再继续调用自身,从而结束递归。
3. 处理子问题:在每次调用自身时,需要将原始参数转换为更小的参数,并传入新的函数或方法中。
这样就可以不断地处理子问题。
4. 合并结果:当所有子问题都得到了解决后,在最后一次调用自身时,将所有结果合并起来,并返回给调用方。
递归算法的优点在于能够简化代码结构,使代码更加清晰易懂。
同时,递归算法也可以处理复杂的问题,并且通常比迭代算法更加高效。
但是,递归算法也有一些缺点。
例如,递归算法通常需要大量的栈空间来存储函数或方法的调用信息,从而导致内存占用过高。
下面是一个示例程序,演示了如何使用递归算法来实现阶乘运算:public class Factorial {public static int factorial(int n) {if (n == 0) { // 设定停止条件return 1;} else {return n * factorial(n-1); // 处理子问题}}public static void main(String[] args) {int result = factorial(5); // 调用函数System.out.println(result);}}在上述程序中,函数factorial()接受一个参数n,并返回n的阶乘。
java递归写法递归是一种重要的算法思想,它可以用来解决很多问题,例如数学中的阶乘、斐波那契数列、树的遍历等。
在Java中,递归的写法可以很简单,但是如果不小心就会出现栈溢出等问题。
本文将介绍Java中递归的写法,以及如何避免递归过程中出现的一些问题。
一、递归的概念递归是一种函数调用自身的算法思想。
它通过将一个问题分解为更小的子问题来解决问题。
递归算法的基本思路是:当问题的规模足够小时,直接求解;否则,将问题分解为规模更小的子问题,递归地解决子问题,最后将子问题的结果合并起来得到原问题的解。
递归算法有两个重要的特点:一是递归调用函数本身;二是需要有一个递归终止条件。
递归调用函数本身是为了将问题规模缩小,递归终止条件是为了避免无限递归。
二、递归的实现递归的实现需要考虑两个方面:递归调用和递归终止条件。
递归调用是指在函数中调用自身,递归终止条件是指当问题规模足够小时,直接求解。
例如,求n的阶乘可以使用递归实现。
当n等于1时,阶乘为1;否则,阶乘为n乘以(n-1)的阶乘。
代码如下:```javapublic class Factorial {public static long factorial(int n) {if (n == 1) {return 1;} else {return n * factorial(n - 1);}}}```这段代码中,递归调用在return语句中,递归终止条件是当n 等于1时,直接返回1。
三、递归的应用递归算法可以用来解决很多问题,例如数学中的阶乘、斐波那契数列、树的遍历等。
下面分别介绍这些应用。
1. 阶乘阶乘是指从1到n的所有正整数相乘的积。
例如,5的阶乘为5x4x3x2x1=120。
使用递归算法可以很容易地求出n的阶乘。
代码如下:```javapublic class Factorial {public static long factorial(int n) {if (n == 1) {return 1;} else {return n * factorial(n - 1);}}}```2. 斐波那契数列斐波那契数列是指第n个数等于前两个数之和。
java算法-递归算法递归算法是指在函数的执行过程中,不断地调用自身来解决问题的一种算法,也称为递归函数。
它是一种很有用的技术,用来解决一些复杂的问题。
在Java语言中,递归算法被广泛地应用在各种领域,例如树结构的遍历、图结构的遍历、排序算法、分治算法等。
递归算法的基本思想是:将一个大问题分解成若干个小问题来解决,每个小问题都是与原问题相同的结构。
当小问题满足一定条件时,递归结束,逐级返回答案,将每个小问题的答案合并起来,最终得到大问题的答案。
递归算法的优点在于它简洁、直观、易于理解,而且可以轻松地解决复杂的问题。
但是,递归算法通常会占用大量的内存和时间,而且容易引发死循环等错误。
因此,在使用递归算法时,应该注意编写正确的条件和基准情况,确保递归的正确性和性能。
在Java语言中,递归算法通常可以用函数来实现,例如:```public static int factorial(int n) {if (n <= 1) {return 1;} else {return n * factorial(n - 1);}}```上述代码实现了阶乘算法,当n <= 1时,递归结束,返回1;当n > 1时,递归调用factorial(n - 1)来计算n的阶乘,逐级返回结果,最终得到n的阶乘。
除了阶乘算法,递归算法还可以实现很多其他算法,例如斐波那契数列算法、汉诺塔问题算法、快速排序算法、归并排序算法等。
这些算法均是利用递归算法的思想,将一个大问题分解成若干个小问题来解决。
总之,递归算法是一种非常有用的算法技术,可以用来解决各种复杂的问题。
它的优点在于它简洁、直观、易于理解,而且可以轻松地解决复杂的问题。
但是,在使用递归算法时,应该注意编写正确的条件和基准情况,确保递归的正确性和性能。
递归算法在计算机科学领域中的应用非常广泛,从数据结构到算法,递归的思想几乎无处不在。
下面我们来介绍一些递归算法的实际应用。
java解析四则运算为树形的方法概述及解释说明1. 引言1.1 概述:本文将讨论Java解析四则运算为树形结构的方法。
四则运算是数学中最基础的运算,包括加法、减法、乘法和除法。
通过对四则运算表达式进行解析,可以将其转化为树形结构,以提供更方便的处理和计算方式。
在本文中,我们将介绍四则运算及其解析方式的简介,并重点关注树形结构在这种解析中的应用。
1.2 文章结构:本文共分为5个部分:引言、正文、解释说明、结论和后记。
在引言部分,我们将给出文章的概述,简述整篇文章的内容与目标。
在正文部分,我们将详细介绍四则运算及其解析方式的简介,并探究树形结构在这种解析中的作用。
在解释说明部分,我们会阐述将四则运算表达式转化为树形结构的基本概念和原理,并讨论Java中实现这一过程的方法。
接着,我们还会探讨树形结构在四则运算解析中的优势和应用场景。
在结论部分,我们将总结文章要点和重点论述内容,并对Java解析四则运算为树形的方法进行评价并展望未来的发展方向。
最后,在后记部分,我们将留下一些附加信息和感想。
1.3 目的:本文的目的是提供一个全面且易懂的解析四则运算为树形结构的方法,并探讨这种方法在Java中的应用。
通过深入了解四则运算的解析和树形结构的应用,读者可以更好地理解并使用这些技术,进一步提高程序设计和算法实现能力。
本文还旨在为Java开发者提供一个可靠而有效的工具,以便于他们处理复杂的四则运算表达式。
跟随本文学习并实践这种方法可以增强编码技巧和培养抽象思维能力,在日常开发中收获不少益处。
2. 正文:2.1 四则运算及其解析方式简介:在数学中,四则运算指的是加法、减法、乘法和除法这四种基本运算。
它们是最常见和基础的数学运算,广泛应用于各个领域。
在计算机科学中,我们通常需要将四则运算表达式进行解析,以便计算机能够理解和执行。
2.2 树形结构在四则运算解析中的应用:树形结构是一种非常适合表示嵌套层次关系的数据结构。
Java实现四则运算本次使⽤java语⾔,实现了四则运算习题的⽣成。
⼀、主要功能:(1)算式个数(2)是否有乘除法(3)结果集数值范围(4)加减法有⽆负数(5)除法有⽆余数(6)除法出现⼩数是否⽀持分数显⽰(7)选择⽣成算式导⼊的⽂件(8)输出打印每⾏个数⼆、代码实现:(1)IFormulaGenerationpackage cn.zhl.software;import java.util.Map;public interface IFormulaGeneration {//加法⽣成接⼝,结果范围,加法有⽆负数,⽣成个数public Map<String,Integer> Add(int resultRange,boolean is,int num);//减法⽣成接⼝,结果范围,减法有⽆负数,⽣成个数public Map<String,Integer> Sub(int resultRange,boolean is,int num);//乘法⽣成接⼝,⽣成个数public Map<String,Integer> Mul(int resultRange,int num);//除法⽣成接⼝,结果范围,除法有⽆余数,是否⽀持分数,⽣成个数public Map<String,String> Div(int resultRange,boolean is,boolean is2,int num);//检测算式是否存在重复,如果存在返回truepublic boolean Repeat(Map<?,?> map,String formula);//⽣成特定范围的数值public int nextInt(int min, int max);//算法⽣成器:算式个数,是否有乘除法,数值范围,加减法有⽆负数,除法⼜⽆余数,是否⽀持分数,打印每⾏个数 public Map<String,?> FormulaCustom(int formulaNum,boolean if_MulDiv,int range,boolean ifNeg_AddSub,boolean ifRem_Div,boolean ifRed_Div,int lineNum);}(2)FormulaRealizationpackage cn.zhl.software;import java.util.HashMap;import java.util.Map;import java.util.Random;import java.util.Set;public class FormulaRealization implements IFormulaGeneration {Random random = new Random();@Overridepublic Map<String, Integer> Add(int resultRange, boolean is, int num) {if (resultRange < 0) {resultRange = -resultRange;}Map<String, Integer> addMap = new HashMap<>();int r1 = 0, r2 = 0, n = 0;String formula = "";for (; n < num; ) {r1 = nextInt(-resultRange, resultRange);if (is) {//加法允许出现负数r2 = nextInt(-resultRange - r1, resultRange - r1);} else {r2 = nextInt(-r1, resultRange - r1);}formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "+" + (r2 < 0 ? "(" + r2 + ")" : r2);if (Repeat(addMap, formula)) {}return addMap;}@Overridepublic Map<String, Integer> Sub(int resultRange, boolean is, int num) { if (resultRange < 0) {resultRange = -resultRange;}Map<String, Integer> subMap = new HashMap<>();int r1 = 0, r2 = 0, n = 0;String formula = "";for (; n < num; ) {r1 = nextInt(-resultRange, resultRange);if (is) {//加法允许出现负数r2 = nextInt(-resultRange + r1, resultRange + r1);} else {r2 = nextInt(r1, resultRange + r1);}formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "-" + (r2 < 0 ? "(" + r2 + ")" : r2); if (Repeat(subMap, formula)) {subMap.put(formula, r1 - r2);n++;}}return subMap;}@Overridepublic Map<String, Integer> Mul(int resultRange, int num) {if (resultRange == 0) {resultRange = 1;}if (resultRange < 0) {resultRange = -resultRange;String formula = "";for (; n < num; ) {while (r1 == 0) {r1 = nextInt(-resultRange, resultRange);}r2 = nextInt(-(int) (resultRange / Math.abs(r1)), (int) (resultRange / Math.abs(r1))); formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "*" + (r2 < 0 ? "(" + r2 + ")" : r2);if (Repeat(mulMap, formula)) {mulMap.put(formula, r1 * r2);n++;r1 = nextInt(-resultRange, resultRange);}}return mulMap;}@Overridepublic Map<String, String> Div(int resultRange, boolean is, boolean is2, int num) { if (resultRange == 0) {resultRange = 1;}if (resultRange < 0) {resultRange = -resultRange;}Map<String, String> divMap = new HashMap<>();int r1 = 0, r2 = 0, n = 0;String formula = "";for (; n < num; ) {//r1 = nextInt(-resultRange, resultRange);while (r2 == 0) {r2 = nextInt(-resultRange, resultRange);}if (!is) {//除法没有余数r1 = r2 * nextInt(-(resultRange), resultRange);} else {//有余数r1 = nextInt(-resultRange, resultRange);}formula = (r1 < 0 ? "(" + r1 + ")" : r1) + "/" + (r2 < 0 ? "(" + r2 + ")" : r2);if (Repeat(divMap, formula)) {String result = "";if (is && is2) {//有余数且化为分数if(r1*r2<0){result = "-"+fracReduction(Math.abs(r1), Math.abs(r2));}else {result = fracReduction(Math.abs(r1), Math.abs(r2));}if(r1%r2==0){result = ((double) r1 / r2) + "";}if (is) {result = ((double) r1 / r2) + "";}}if(r1==0){result=0.0+"";}if (r1==-r2){result="-1.0";}divMap.put(formula, result);n++;}}return divMap;}@Overridepublic boolean Repeat(Map<?, ?> map, String formula) { if (map.isEmpty()) {return true;} else {Set<String> strings = (Set<String>) map.keySet(); for (String string : strings) {//如果当前算式与前⾯算式重复返回falseif (string.equals(formula)) {return false;}}//如果当前算式与前⾯算式不存在重复返回truereturn true;}}@Overridepublic int nextInt(int min, int max) {if (min == max) {return max;}return random.nextInt(max - min + 1) + min;public String fracReduction(int numerator, int denominator) {//找到最⼤公约数,然后分别处以最⼤公约数int m = numerator;int n = denominator;int r;while (numerator > 0) {r = denominator % numerator;denominator = numerator;numerator = r;}// if ((m / denominator)==-(n / denominator)){// return "-1.0";// }return m / denominator + "/" + n / denominator;}@Override//算法⽣成器:算式个数,是否有乘除法,数值范围,加减法有⽆负数,除法⼜⽆余数,是否⽀持分数,打印每⾏个数public Map<String, ?> FormulaCustom(int formulaNum, boolean if_MulDiv, int range, boolean ifNeg_AddSub, boolean ifRem_Div, boolean ifRed_Div, int lineNum) {int add = 0, sub = 0, mul = 0, div = 0;add = nextInt(formulaNum/5,formulaNum/3);sub = nextInt((formulaNum - add)/4,(formulaNum - add)/2);mul = nextInt((formulaNum - add - sub)/3,(formulaNum - add - sub)/1);div = formulaNum - add - sub - mul;Map map = new HashMap();if (if_MulDiv) {//如果存在乘除法将算式总数分为四份Map<String, Integer> addMap = Add(range, ifNeg_AddSub, add);Map<String, Integer> subMap = Sub(range, ifNeg_AddSub, sub);Map<String, Integer> mulMap = Mul(range, mul);Map<String, String> divMap = Div(range, ifRem_Div, ifRed_Div, div);map.putAll(addMap);map.putAll(subMap);map.putAll(mulMap);map.putAll(divMap);} else {//不存在则分为两份map.putAll(addMap);map.putAll(subMap);}return map;}}(3)FormulaRealizationTestpackage cn.zhl.test;import cn.zhl.software.FormulaRealization;import org.junit.Test;import java.util.Map;import java.util.Set;public class FormulaRealizationTest {FormulaRealization formulaRealization = new FormulaRealization();@Testpublic void testAdd() {Map<String, Integer> add = formulaRealization.Add(100, false, 5); for (String s : add.keySet()) {System.out.print(s+"="+add.get(s)+" ");}}@Testpublic void testSub() {Map<String, Integer> sub = formulaRealization.Sub(100, true, 5); for (String s : sub.keySet()) {System.out.print(s+"="+sub.get(s)+" ");}}@TestSystem.out.print(s+"="+mul.get(s)+" ");}}@Testpublic void testDiv() {Map<String, String> div = formulaRealization.Div(100, true, true, 5);for (String s : div.keySet()) {System.out.print(s+"="+div.get(s)+" ");}}@Testpublic void test1() {String div = formulaRealization.fracReduction(25,5);System.out.print(div);}}(4)IFileGenerationpackage cn.zhl.fileCreate;import java.util.Map;public interface IFileGeneration {//⽤于将产⽣的算式写⼊到⽂件中public void fileShow(Map<String,?> stringMap,int lineNum,String fileName); }(5)FileRealizationpackage cn.zhl.fileCreate;import java.io.File;import java.io.FileWriter;import java.io.IOException;@Overridepublic void fileShow(Map<String,?> stringMap, int lineNum, String fileName) {int n=0;String answerName=fileName+"_Answer.txt";fileName=fileName+".txt";/*File file1 = new File("\\cn\\zhl\\formulaFile\\" + fileName);File file2 = new File("\\cn\\zhl\\formulaFile\\" + answerName);*/File file1 = new File("Arithmetic_question_generation_system\\src\\cn\\zhl\\formulaFile\\"+fileName);File file2 = new File("Arithmetic_question_generation_system\\src\\cn\\zhl\\formulaFile\\"+answerName);for (String s : stringMap.keySet()) {n++;try(FileWriter formulaWriter = new FileWriter(file1,true); FileWriter answerWriter = new FileWriter(file2,true)) { formulaWriter.write(s+"= ");answerWriter.write(s+"="+stringMap.get(s)+" ");if(n%lineNum==0){formulaWriter.write("\n");answerWriter.write("\n");}} catch (IOException e) {e.printStackTrace();System.out.println("未成功将算式保存到"+fileName+"中,答案保存到"+answerName+"中,请联系开发⼈员!"); }}System.out.println("已成功将算式保存到"+fileName+"中,答案保存到"+answerName+"中,欢迎您的下次使⽤!"); }}(6)FormulaCustomTestpackage cn.zhl.software;import cn.zhl.fileCreate.FileRealization;import java.io.File;import java.io.FileWriter;import java.io.IOException;public class FormulaCustomTest {public static void main(String[] args) {int formulaNum;boolean if_MulDiv;int range;boolean ifNeg_AddSub;boolean ifRem_Div;boolean ifRed_Div;int lineNum;Scanner scanner = new Scanner(System.in);System.out.println("请输⼊需要算式个数:");formulaNum=scanner.nextInt();System.out.println("请输⼊需要乘除法(Y/N):");if(scanner.next().equals("y")||scanner.next().equals("Y")){if_MulDiv=true;}else {if_MulDiv=false;}System.out.println("请输⼊需要结果集范围(默认-n~n):");range=scanner.nextInt();System.out.println("请输⼊允许加减法出现负数(Y/N):");if(scanner.next().equals("y")||scanner.next().equals("Y")){ifNeg_AddSub=true;}else {ifNeg_AddSub=false;}System.out.println("请输⼊允许除法出现⼩数(Y/N):");if(scanner.next().equals("y")||scanner.next().equals("Y")){ifRem_Div=true;}else {ifRem_Div=false;}System.out.println("请输⼊允许除法结果换算成分数(Y/N):"); if(scanner.next().equals("y")||scanner.next().equals("Y")){ifRed_Div=true;}else {lineNum=scanner.nextInt();//⽂件名String fileName="";System.out.println("请输⼊算式需要导⼊的⽂件名:");fileName=scanner.next();System.out.println("定制完成,正在随机⽣成算式。
java递归详解递归是一种常见的编程技巧,它在解决问题时通过调用自身来实现。
在Java中,递归是一种强大而灵活的工具,可以用于解决各种问题。
本文将详细介绍Java递归的原理、应用场景以及一些注意事项。
首先,让我们来了解递归的原理。
递归函数是一种特殊的函数,它在执行过程中会调用自身。
递归函数通常包含两个部分:基本情况和递归调用。
基本情况是递归函数停止调用自身的条件,而递归调用是递归函数在满足基本情况之前一直调用自身。
递归函数的执行过程可以用一个栈来模拟。
每次递归调用时,函数的局部变量和参数都会被保存在栈中,直到满足基本情况时才会逐个弹出栈。
这种栈的结构被称为递归栈。
递归在解决问题时具有很大的灵活性。
它可以用于解决各种问题,如计算阶乘、斐波那契数列、二叉树遍历等。
下面我们以计算阶乘为例来说明递归的应用。
计算阶乘是一个经典的递归问题。
阶乘的定义是n的阶乘等于n乘以(n-1)的阶乘,其中0的阶乘定义为1。
我们可以使用递归函数来计算阶乘。
```javapublic class Factorial {public static int factorial(int n) {if (n == 0) {return 1;} else {return n * factorial(n - 1);}}public static void main(String[] args) {int n = 5;int result = factorial(n);System.out.println("The factorial of " + n + " is " + result);}}```在上面的代码中,factorial函数是一个递归函数。
当n等于0时,满足基本情况,函数返回1。
否则,函数调用自身,并将n减1作为参数传递给递归调用。
最终,递归函数的返回值是n乘以(n-1)的阶乘。
递归函数的使用需要注意一些问题。
Java的递归算法详解⽬录⼀、介绍1、介绍2、案例⼆、迷宫问题三、⼋皇后问题四、汉诺塔问题1、问题2、思想3、代码总结⼀、介绍1、介绍递归:递归就是⽅法⾃⼰调⽤⾃⼰,每次调⽤时传⼊不同的变量。
递归有助于编程者解决复杂的问题,同时可以让代码变得简洁。
迭代和递归区别:迭代使⽤的是循环结构,递归使⽤的选择结构。
使⽤递归能使程序的结构更清晰、更简洁、更容易让⼈理解,从⽽减少读懂代码的时间。
其时间复杂度就是递归的次数。
但⼤量的递归调⽤会建⽴函数的副本,会消耗⼤量的时间和内存,⽽迭代则不需要此种付出。
递归函数分为调⽤和回退阶段,递归的回退顺序是它调⽤顺序的逆序。
分治:当⼀个问题规模较⼤且不易求解的时候,就可以考虑将问题分成⼏个⼩的模块,逐⼀解决。
2、案例兔⼦繁殖的问题。
(斐波那契数列)。
计算 n! 。
任意长度的字符串反向输出。
折半查找算法的递归实现。
汉诺塔问题⼋皇后问题⼆、迷宫问题问题:寻找⼀条从起始点到达终点的有效路径。
代码⽰例:迷宫public class MiGong {/*** 0:该点没有⾛过, 1:表⽰墙, 2:可以⾛, 3:该点已经⾛过,但是⾛不通\ * 策略: 下->右->上->左, 如果该点⾛不通,再回溯*/private int[][] map;private int desX;private int desY;/*** 构建 row*col的迷宫** @param row ⾏* @param col 列*/public MiGong(int row, int col) {if (row <= 0 || col <= 0) {return;}map = new int[row][col];// 默认上下左右全部为墙for (int i = 0; i < col; i++) {map[0][i] = 1;map[row - 1][i] = 1;}for (int i = 0; i < row; i++) {map[i][0] = 1;map[i][col - 1] = 1;}}/*** 在迷宫内部添加挡板** @param i 横坐标* @param j 纵坐标*/public void addBaffle(int i, int j) {if (map == null) {return;}// 外⾯⼀周都是墙if (i > 0 && i < map.length - 1 && j > 0 && j < map[0].length - 1) { map[i][j] = 1;}}/*** 设置迷宫的终点位置** @param desX 横坐标* @param desY 纵坐标*/public void setDes(int desX, int desY) {this.desX = desX;this.desY = desY;}public boolean setWay(int i, int j) {// 通路已经找到if (map[desX][desY] == 2) {return true;} else {if (map[i][j] != 0) {return false;}// map[i][j] == 0 按照策略下->右->上->左递归// 假定该点是可以⾛通.map[i][j] = 2;if (setWay(i + 1, j)) {return true;} else if (setWay(i, j + 1)) {return true;} else if (setWay(i - 1, j)) {return true;} else if (setWay(i, j - 1)) {return true;} else {// 说明该点是⾛不通,是死路map[i][j] = 3;return false;}}}// 显⽰地图public void show() {for (int i = 0; i < map.length; i++) {for (int j = 0; j < map[0].length; j++) {System.out.print(map[i][j] + " ");}System.out.println();}}} 代码⽰例:测试类// 测试类public class Main {public static void main(String[] args) {MiGong miGong = new MiGong(8, 7);miGong.addBaffle(3, 1);miGong.addBaffle(3, 2);miGong.setDes(6, 5); // 设置⽬的地System.out.println("初始地图的情况");miGong.show();miGong.setWay(1, 1); // 设置起始位置System.out.println("⼩球⾛过的路径,地图的情况");miGong.show();}}// 结果初始地图的情况1 1 1 1 1 1 11 0 0 0 0 0 11 0 0 0 0 0 11 1 1 0 0 0 11 0 0 0 0 0 11 0 0 0 0 0 11 0 0 0 0 0 11 1 1 1 1 1 1⼩球⾛过的路径,地图的情况1 1 1 1 1 1 11 2 0 0 0 0 11 2 2 2 0 0 11 1 12 0 0 11 0 02 0 0 11 0 02 0 0 11 0 02 2 2 11 1 1 1 1 1 1三、⼋皇后问题问题:在8×8格的国际象棋上摆放⼋个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上,问有多少种摆法。
递归--四则运算表达式求值输⼊为四则运算表达式,仅由整数、+、-、*、/ 、(、)组成,没有空格,要求求其值。
假设运算符结果都是整数。
"/"结果也是整数解题思想:因为四则运算有优先级,所以在设计递归的时候,需要注意。
这⾥设计为:表达式-项-因⼦-带括号表达式或整数,这⾥只是给了个名称上的定义,可以不⽤具体的纠结什么是项、什么是因⼦,这些名称你都可以⾃⼰定义。
关键的是要好好理解,“+,-”的运算级别最低,“()”括号的运算级别最好,“乘除”居中,因此递归的调⽤也是参照这样来设计的。
表达式可以是⼀个单独的项,也可以是2个项之间进⾏加、减,项可以是因⼦,或者多个因⼦乘除,因⼦是整数或者再是⼀个带括号的表达式。
举个例⼦:2+3*4,读⼊2后,接着读⼊+符号,接下来是不能直接求2+3的,需要继续下⼀项,递归遍历,就是先计算3*4,运算是先返回3个⼀个整数,然后因⼦做*运算,接着继续递归调⽤,返回4是个整数,然后把3*4的结果返回给上⼀个递归调⽤的函数,把这个计算结果求出来后,再与2相加,这样就很好的解决了运算符优先级的问题。
简单理解:Python代码实现:"""输⼊:(2+3)*(5+7)+9/3输出: 63"""#输⼊需要计算的表达式in_exp = ""#表达式的每个字符的位置pos = 0#计算表达式的值def Expression_value():global in_exp,pos#计算第⼀个表达式的值result = Term_value()more = Truewhile more :pos = pos + 1#判断访问list是否越界if (pos >= len(in_exp)):more = Falsebreakop = in_exp[pos]if (op == "+"or op == "-"):pos = pos + 1value = Term_value()if (op == "+"):result += valueelse:result -= valueelse:more = Falsereturn result#计算项的值def Term_value():global in_exp,pos# 计算第⼀个表达式的值result = Factor_value()more = Truewhile (more):pos = pos + 1# 判断访问list是否越界if (pos >= len(in_exp)):more = Falsebreakop = in_exp[pos]if (op == "*"or op == "/"):pos = pos + 1value = Factor_value()if (op == "*"):result *= valueelse:result /= valueelse:pos = pos - 1more = Falsereturn result#计算因⼦的值def Factor_value():global in_exp,posresult = 0c = in_exp[pos]if (c == "("):pos = pos + 1result = Expression_value()else:while (c.isdigit()):result = 10*result + int(c)pos = pos + 1#判断是否超过list的长度if (pos == len(in_exp)):breakc = in_exp[pos]pos = pos - 1#while (isdigit(c))#result = 10 * result + c - '0';#在ASCII编码中, 0~9 的编码是 0x30~0x39, 所以当c在‘0'~'9'的范围中时,c - '0' 就相当于计算c的实际数值, #例如 c 是 '1', 则 c - '0' = 1, 把字符值转为数字值1了return resultdef main():global in_expin_exp = input("请输⼊需要计算的表达式:")rtn = Expression_value()print("表达式: "+in_exp+"的运算结果为:%d" %rtn)if (__name__ == "__main__"):main()。
四则混合运算的算符优先算法Java实现它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。
它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。
举例:(3 + 4) × 5 - 6 就是中缀表达式- × + 3 4 5 6 前缀表达式3 4 + 5 × 6 - 后缀表达式中缀表达式(中缀记法)中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。
中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。
对计算机来说,计算前缀或后缀表达式的值非常简单。
前缀表达式(前缀记法、波兰式)前缀表达式的运算符位于操作数之前。
前缀表达式的计算机求值:从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。
例如前缀表达式“- × + 3 4 5 6”:(1) 从右至左扫描,将6、5、4、3压入堆栈;(2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈;(3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈;(4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
可以看出,用计算机计算前缀表达式的值是很容易的。
将中缀表达式转换为前缀表达式:遵循以下步骤:(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;(2) 从右至左扫描中缀表达式;(3) 遇到操作数时,将其压入S2;(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:(4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;(4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;(5) 遇到括号时:(5-1) 如果是右括号“)”,则直接压入S1;(5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;(6) 重复步骤(2)至(5),直到表达式的最左边;(7) 将S1中剩余的运算符依次弹出并压入S2;(8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
递归算法递归算法是一种常见的问题解决方法,它通过将一个大问题划分成若干个相同或相似的子问题来解决。
递归算法在计算机科学中具有广泛的应用,特别是在数据结构和算法中。
什么是递归?递归是指一个函数调用自身的过程。
在编写递归函数时,我们需要定义一个基本情况(base case),以及一个或多个递归情况(recursive case)。
基本情况通常是指当输入满足某个条件时,函数直接返回结果而不再进行递归调用。
而递归情况则是指当输入不满足基本情况时,函数将自己调用,并缩小问题规模,直到最终达到基本情况。
适合使用递归的场景使用递归算法可以解决一些问题,例如:•数学上的阶乘计算•斐波那契数列•形状的无限嵌套•文件系统遍历•数据结构中的树和图操作适合使用循环的场景虽然递归算法有其优势,但也有一些场景不太适合使用它。
例如:•需要大量的递归调用,可能导致栈溢出•递归算法可能会重复计算相同的子问题,导致性能下降•递归算法通常需要额外的内存空间来保存每个递归调用的状态对于这些场景,使用循环(迭代)算法可能更加合适。
递归算法示例:阶乘计算让我们以一个经典的例子来说明递归算法:计算一个数的阶乘。
public class Factorial {public static int factorial(int n) {if (n == 0 || n == 1) { // 基本情况return 1;} else { // 递归情况return n * factorial(n - 1);}}public static void main(String[] args) {int n = 5;int result = factorial(n);System.out.println("The factorial of " + n + " is " + result);}}在上面的代码中,我们定义了一个静态方法factorial来计算给定数n的阶乘。
JAVA四则运算算法⼀、程序要求解析⼀般数学算式,实现简单的带括号的加减乘除运算。
⼆、基本思路前⾯两篇介绍了直接解析字符串和⽤数组容器辅助解析的两种⽅式,这次再介绍最常⽤的解析算法——解析后缀表达式(逆波兰表达式)。
三、逆波兰表达式及其得到算法1、逆波兰表达式也即后缀表达式,指的是不包含括号,运算符放在两个运算对象的后⾯,所有的计算按运算符出现的顺序,严格从左向右进⾏(不再考虑运算符的优先规则)。
(摘⾃百度),既然没了运算符的优先规则,那么计算机解析起来⾃然容易的多。
对于我们常见的表达式,称为中缀表达式,每个中缀表达式都有对应的后缀表达式。
如:中缀表达式:-2*(1+6/3)+4后缀表达式:-2 1 6 3 / + * 4 +(这⾥为了区分负号和减号,我在数字与数字、数字与符号之间都加了空格,⾄于怎么从中缀表达式得到后缀表达式,后⾯有介绍及参考程序)⽽在解析后缀表达式时,只需要遵守以下原则即可:从左往右遍历遇到数字直接放⼊容器遇到运算符,将最后两个数字取出,进⾏该运算,将结果再放⼊容器遍历结束后,容器中的数字即为运算结果按这个过程⾛下来,⾃然⽽然的想到⽤栈是最合适的。
现只需想办法由输⼊的中缀表达式转为后缀表达式即可完成解析。
2、由中缀表达式得到后缀表达式的算法由中缀表达式得到后缀表达式,只要遵守以下步骤即可:⾸先设置运算符的优先级(这样设置也是为了简化程序):”null” 栈顶若为空,假设优先级为0“(” 优先级设为1“+-” 优先级设为2“*/” 优先级设为3从左向右遍历中缀表达式遇到数字直接输出遇到符号遇到左括号,直接压栈遇到右括号,弹栈输出直到弹出左括号(左括号不输出)遇到运算符,⽐较栈顶符号,若该运算符优先级⼤于栈顶,直接压栈;若⼩于栈顶,弹栈输出直到⼤于栈顶,然后将改运算符压栈。
最后将符合栈弹栈并输出现根据这个原则,⼿动模拟⼀遍转换过程:还是以-2*(1+6/3)+4为例四、代码⼀环境:Eclipse Java EE IDE(Version: Oxygen.1a Release (4.7.1a))jdk1.8.0_131先写⼀个最基本的两位数四则运算⽅法,⽐较简单,没有写注释:private static double doubleCal(double a1, double a2, char operator) throws Exception {switch (operator) {case '+':return a1 + a2;case '-':return a1 - a2;case '*':return a1 * a2;case '/':return a1 / a2;default:break;}throw new Exception("illegal operator!");} 写⼀个获得优先级的⽅法:private static int getPriority(String s) throws Exception {if(s==null) return 0;switch(s) {case "(":return 1;case "+":;case "-":return 2;case "*":;case "/":return 3;default:break;}throw new Exception("illegal operator!");}将中缀表达式转变为后缀表达式:private static String toSufExpr(String expr) throws Exception {System.out.println("将"+expr+"解析为后缀表达式...");/*返回结果字符串*/StringBuffer sufExpr = new StringBuffer();/*盛放运算符的栈*/Stack<String> operator = new Stack<String>();operator.push(null);//在栈顶压⼈⼀个null,配合它的优先级,⽬的是减少下⾯程序的判断/* 将expr打散分散成运算数和运算符 */Pattern p = pile("(?<!\\d)-?\\d+(\\.\\d+)?|[+\\-*/()]");//这个正则为匹配表达式中的数字或运算符Matcher m = p.matcher(expr);while (m.find()) {String temp = m.group();if (temp.matches("[+\\-*/()]")) { //是运算符if (temp.equals("(")) { //遇到左括号,直接压栈operator.push(temp);System.out.println("'('压栈");} else if (temp.equals(")")) { //遇到右括号,弹栈输出直到弹出左括号(左括号不输出)String topItem = null;while (!(topItem = operator.pop()).equals("(")) {System.out.println(topItem+"弹栈");sufExpr.append(topItem+" ");System.out.println("输出:"+sufExpr);}} else {//遇到运算符,⽐较栈顶符号,若该运算符优先级⼤于栈顶,直接压栈;若⼩于栈顶,弹栈输出直到⼤于栈顶,然后将改运算符压栈。
java 递归讲解Java递归是一种编程技巧,它指的是在一个方法中调用自身的方法。
递归方法通常用于解决具有相似子问题的复杂问题。
通过将问题分解为较小的子问题,并在解决较小问题时重复调用同一方法,可以大大简化代码并提高效率。
以下是关于Java递归的一些讲解:1. 递归的基本概念:在Java中,递归方法是指在方法体中调用自身的同名方法。
当一个方法在执行过程中再次调用自身时,就形成了递归。
递归的关键在于找到一个基准条件,即一个简单易懂的情况,当满足这个条件时,递归就可以停止,并将结果返回给上层方法。
2. 递归的优点:递归有助于简化代码,提高代码的可读性和可维护性。
它可以让程序员更容易地解决复杂问题,同时减少代码量。
递归方法还允许我们利用已有的代码来解决相似的问题,从而提高代码的复用性。
3. 递归的缺点:然而,递归也存在一些缺点。
由于递归方法在执行过程中会不断调用自身,这可能导致程序陷入无限循环,从而导致栈溢出错误。
因此,在使用递归时,需要谨慎寻找基准条件,以确保递归能够在合适的时候停止。
4. 递归案例:案例1:递归打印数字```javapublic static void test(int n) {if (n > 2) {test(n - 1);} else {System.out.println(n);}}```案例2:阶乘计算```javapublic static int factorial(int n) { if (n == 0) {return 1;} else {return n * factorial(n - 1);}}```5. 递归的实现原理:Java中的递归方法是通过栈来实现的。
当一个方法调用另一个方法时,系统会为第二个方法分配一个栈空间。
随着递归层次的加深,栈空间会不断增长。
当递归到达基准条件时,方法开始返回结果,栈空间逐渐减小。
最后,递归调用链中的所有方法都执行完毕,栈空间完全释放。
递归算法 java一、递归算法的概念递归算法是指在解决问题时,调用自身函数来解决子问题的方法。
递归算法通常包含两个部分:基本情况和递归情况。
基本情况是指问题可以直接解决,而不需要再次调用函数;递归情况则是指问题需要进一步拆分为子问题,并通过调用自身函数来解决。
二、递归算法的优点和缺点优点:1. 代码简洁易懂:递归算法通常使用较少的代码就能完成任务,并且代码结构清晰易懂。
2. 解题思路清晰:使用递归算法可以将复杂的问题分解为简单的子问题,从而更容易理解和解决。
缺点:1. 性能较差:由于递归算法需要频繁地调用自身函数,因此会占用大量的栈空间,导致程序运行速度变慢。
2. 可能会导致栈溢出:如果递归深度过大,可能会导致栈空间不足而导致程序崩溃。
三、Java中实现递归算法的方式Java中实现递归算法有两种方式:方法递归和尾递归。
方法递归是指在调用自身函数时,没有任何其他语句需要执行;尾递归则是指在调用自身函数时,最后一步操作是调用自身函数。
1. 方法递归方法递归通常包含两个部分:基本情况和递归情况。
基本情况是指问题可以直接解决,而不需要再次调用函数;递归情况则是指问题需要进一步拆分为子问题,并通过调用自身函数来解决。
例如,下面的代码演示了如何使用方法递归来计算阶乘:```public static int factorial(int n) {if (n == 0) { // 基本情况return 1;} else { // 递归情况return n * factorial(n - 1);}}```2. 尾递归尾递归通常包含两个部分:基本情况和尾调用。
基本情况是指问题可以直接解决,而不需要再次调用函数;尾调用则是指最后一步操作是调用自身函数。
例如,下面的代码演示了如何使用尾递归来计算阶乘:```public static int factorial(int n, int acc) {if (n == 0) { // 基本情况return acc;} else { // 尾调用return factorial(n - 1, acc * n);}}```四、递归算法的应用场景递归算法在许多问题中都有广泛的应用,例如:1. 排序算法:快速排序和归并排序等排序算法都使用了递归算法。
四则运算 java四则运算是数学中最基础的运算方式,包括加法、减法、乘法和除法。
在计算机编程中,四则运算是一项基本的功能,尤其是在Java 语言中。
本文将围绕Java中的四则运算展开,介绍其基本概念、用法和注意事项。
一、加法运算加法是最基本的运算之一,用于计算两个数的和。
在Java中,使用加号(+)进行加法运算。
例如,计算两个整数的和可以使用以下代码:int a = 5;int b = 3;int sum = a + b;System.out.println("两个整数的和为:" + sum);二、减法运算减法也是常用的运算方式,用于计算两个数的差。
在Java中,使用减号(-)进行减法运算。
例如,计算两个整数的差可以使用以下代码:int a = 5;int b = 3;int difference = a - b;System.out.println("两个整数的差为:" + difference);三、乘法运算乘法是常用的运算方式,用于计算两个数的积。
在Java中,使用星号(*)进行乘法运算。
例如,计算两个整数的积可以使用以下代码:int a = 5;int b = 3;int product = a * b;System.out.println("两个整数的积为:" + product);四、除法运算除法是常用的运算方式,用于计算两个数的商。
在Java中,使用斜杠(/)进行除法运算。
例如,计算两个整数的商可以使用以下代码:int a = 5;int b = 3;int quotient = a / b;System.out.println("两个整数的商为:" + quotient);需要注意的是,如果除数为0时,会出现除数为0的异常,需要进行异常处理。
五、运算顺序在四则运算中,有一定的运算顺序。
在Java中,乘法和除法的运算优先级高于加法和减法。
Java算法-递归算法Java 算法 - 递归算法⽬录递归本质是借助栈的数据结构,加上⼀个简单的逻辑算法实现。
递归是⼀种应⽤⾮常⼴泛的算法,很多数据结构和算法都要⽤到递归,⽐如 DFS 深度优先搜索、前中后序⼆叉树遍历等等。
所以,搞懂递归⾮常重要,否则,后⾯复杂⼀些的数据结构和算法学起来就会⽐较吃⼒。
我们以斐波那契数列分析⼀下递归算法。
# 斐波那契数列:后⼀个数等于前两个数之和1 123 5 8 13 21 34 ...1. 如何编写递归1.1 递归的条件究竟什么样的问题可以⽤递归来解决呢?只要同时满⾜以下三个条件,就可以⽤递归来解决:1. ⼀个问题的解可以分解为⼏个⼦问题的解,这些分解后的⼦问题,除了数据规模不同,求解思路完全⼀样。
何为⼦问题?⼦问题就是数据规模更⼩的问题。
在斐波那契数列中,就是求出前两个数之和。
2. 根据分解后的⼦问题,写出递归公式。
在斐波那契数列中,就是 f(n) = f(n -1) + f(n -2)。
3. 存在递归终⽌条件。
把问题分解为⼦问题,把⼦问题再分解为⼦⼦问题,⼀层⼀层分解下去,不能存在⽆限循环,这就需要有终⽌条件。
在斐波那契数列中,存在多个终⽌条件,也就是 f(1) = 1 和 f(2) = 1,这就是递归的终⽌条件。
1.2 如何编写递归代码写递归代码的关键就是找到如何将⼤问题分解为⼩问题的规律,并且基于此写出递推公式,然后再推敲终⽌条件,最后将递推公式和如何将⼤问题分解为⼩问题的规律,并且基于此写出递推公式,然后再推敲终⽌条件,最后将递推公式和终⽌条件翻译成代码。
只要遇到递归,我们就把它抽象成⼀个递推公式,不⽤想⼀层层的调⽤关系,不要试图⽤⼈脑去分解递归的每个步终⽌条件翻译成代码。
骤。
public int fibonacci(int n) {if (n == 1 || n == 2) {return 1;}return fibonacci(n - 1) + fibonacci(n - 2);}2. 总结2.1 注意事项(1)警惕堆栈溢出编写递归代码时,如果递归层次太深,会出现堆栈溢出。