Java中的什么場景使用遞歸,如何使用遞歸
什么是遞歸?
程序調(diào)用自身的編程技巧叫做遞歸。
遞歸有什么優(yōu)點?
遞歸算法:代碼簡潔、清晰,并且容易驗證正確性。在一定的程度上還能幫我們減少很多重復代碼。
迭代和遞歸的區(qū)別
迭代是逐漸逼近,用新值覆蓋舊值,直到滿足條件后結(jié)束,不保存中間值,空間利用率高。
遞歸是將一個問題分解為若干相對小一點的問題,遇到遞歸出口再原路返回,因此必須保存相關(guān)的中間值,這些中間值壓入棧保存,問題規(guī)模較大時會占用大量內(nèi)存。
遞歸的三個條件
- 邊界條件
- 遞歸前進段
- 遞歸返回段
當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。
什么場景下適合使用遞歸
場景一
項目當中菜單很多都是配置的,并且菜單有時候都是分好幾級的,當我給他配置最下級的時候,那么我還得把他的上級保存起來才能用,但是我們又不確定他有幾個上級,這個時候可以采用遞歸調(diào)用。
public void packageParent(Set<String> parentIdSet) {
Set<String> parentIdSet1 = new HashSet<>();
for (String parentId : parentIdSet) {
MenuOrg menuOrg = new MenuOrg();
Menu menu = menuRepository.findOne(parentId);
if (menu == null) {
continue;
}
menuOrg.setMenuId(menu.getMenuId());
menuOrg.setProType(menu.getProType());
menuOrgRepository.save(menuOrg);
if (menu.getParentId() != null) {
parentIdSet1.add(menu.getParentId());
}
}
//判斷parentIdSet1是否為空
if(!CommonUtils.isCollectionBlankOrEmpty(parentIdSet1)) {
packageParent(parentIdSet1);
}
}
場景二
計算5的階乘
public class Test {
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n) {
if (1 == n)
return 1;
else
return n * f(n-1);
}
}
此題中,按照遞歸的三個條件來分析:
(1)邊界條件:階乘,乘到最后一個數(shù),即1的時候,返回1,程序執(zhí)行到底;
(2)遞歸前進段:當前的參數(shù)不等于1的時候,繼續(xù)調(diào)用自身;
(3)遞歸返回段:從最大的數(shù)開始乘,如果當前參數(shù)是5,那么就是54,即5(5-1),即n*(n-1)
總結(jié)
遞歸中一定有迭代,但是迭代中不一定有遞歸,大部分可以相互轉(zhuǎn)換。
能用迭代的不用遞歸,遞歸調(diào)用函數(shù),計算有重復,浪費空間,并且遞歸太深容易造成堆棧的溢出。
Java 遞歸算法
一、概述
Java遞歸:簡單說就是函數(shù)自身直接或間接調(diào)用函數(shù)的本身。
二、應用場景
若:一個功能在被重復使用,并每次使用時,參與運算的結(jié)果和上一次調(diào)用有關(guān),這時就可以使用遞歸來解決這個問題。
使用要點:
1,遞歸一定明確條件。否則容易棧溢出。
2,注意一下遞歸的次數(shù)。
三、示例
最簡單的遞歸演示
public class recursionDemo {
public static void main(String[] args) {
show();
}
private static void show() {
method();
}
private static void method() {
show();
}
}
四、實際示例
我們都知道 6的二進制是110,那么程序是怎么執(zhí)行的呢?
代碼示例:
public static void main(String[] args) {
toBin(6);
}
private static void toBin(int num) {
if (num>0){
//取余
System.out.println(num%2);
toBin(num/2);
}
}

運行過程:

遞歸演示二:計算1-5,求和
public static void main(String[] args) {
//1-5求和
int sum = getSum(5);
System.out.println(sum);
}
private static int getSum(int num) {
int x=9;
if (num==1){
return 1;
}
return num+getSum(num-1);
}

程序運行圖:

五、遞歸的缺點
在使用遞歸時,一定要考慮遞歸的次數(shù),負責很容易造成虛擬機 “棧溢出”。
仍然使用上面的求和代碼,只是這次將求和基數(shù)變?yōu)?90000000,看看結(jié)果如何
public static void main(String[] args) {
//1-90000000求和
int sum = getSum(90000000);
System.out.println(sum);
}
private static int getSum(int num) {
int x=9;
if (num==1){
return 1;
}
return num+getSum(num-1);
}
果然就造成了虛擬機棧溢出。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring security實現(xiàn)記住我下次自動登錄功能過程詳解
這篇文章主要介紹了Spring security實現(xiàn)記住我下次自動登錄功能過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03
Spring注解@Configuration和@Component區(qū)別詳解
@Component和@Configuration都可以作為配置類,之前一直都沒覺得這兩個用起來有什么差別,可能有時程序跑的和自己想的有所區(qū)別也沒注意到,下面這篇文章主要給大家介紹了關(guān)于Spring注解@Configuration和@Component區(qū)別的相關(guān)資料,需要的朋友可以參考下2023-04-04
MyBatis 實現(xiàn)數(shù)據(jù)的批量新增和刪除的操作
這篇文章主要介紹了MyBatis 實現(xiàn)數(shù)據(jù)的批量新增和刪除的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
java后臺發(fā)起get請求獲取響應數(shù)據(jù)
這篇文章主要為大家詳細介紹了java后臺發(fā)起get請求獲取響應數(shù)據(jù),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-08-08
Java之SpringCloud Eurka注冊錯誤解決方案
這篇文章主要介紹了Java之SpringCloud Eurka注冊錯誤解決方案,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
Spring?Cloud?Gateway?整合?knife4j?聚合接口文檔功能
這篇文章主要介紹了Spring?Cloud?Gateway?整合?knife4j?聚合接口文檔的相關(guān)知識,我們可以基于?Spring?Cloud?Gateway?網(wǎng)關(guān)?+?nacos?+?knife4j?對所有微服務項目的接口文檔進行聚合,從而實現(xiàn)我們想要的文檔管理功能,需要的朋友可以參考下2022-02-02

