遞歸算法

前言

遞歸算法(英語(yǔ):recursion algorithm)在計(jì)算機(jī)科學(xué)中是指一種通過(guò)重復(fù)將問(wèn)題分解為同類(lèi)的子問(wèn)題而解決問(wèn)題的方法。遞歸式方法可以被用于解決很多的計(jì)算機(jī)科學(xué)問(wèn)題明未,因此它是計(jì)算機(jī)科學(xué)中十分重要的一個(gè)概念舔株。絕大多數(shù)編程語(yǔ)言支持函數(shù)的自調(diào)用泉哈,在這些語(yǔ)言中函數(shù)可以通過(guò)調(diào)用自身來(lái)進(jìn)行遞歸旨指。計(jì)算理論可以證明遞歸的作用可以完全取代循環(huán)宏侍,因此在很多函數(shù)編程語(yǔ)言(如Scheme)中習(xí)慣用遞歸來(lái)實(shí)現(xiàn)循環(huán)桥帆。

應(yīng)用場(chǎng)景
  1. 數(shù)據(jù)的定義是按遞歸定義的医增。如Fibonacci函數(shù)慎皱。
  2. 問(wèn)題解法按遞歸算法實(shí)現(xiàn)。如Hanoi問(wèn)題叶骨。
  3. 數(shù)據(jù)的結(jié)構(gòu)形式是按遞歸定義的茫多。如二叉樹(shù)、廣義表等忽刽。 [2]
代碼示例

data數(shù)據(jù)類(lèi)---模擬實(shí)體類(lèi)

package maven.daily.test.mian.recursive;

public class Data {
private String id;
private String name;
private String pid;

Data(String id, String name, String pid) {

    this.id = id;
    this.name = name;
    this.pid = pid;
 }

 public String getId() {
    return id;
 }

 public void setId(String id) {
    this.id = id;
 }

 public String getName() {
    return name;
 }

 public void setName(String name) {
    this.name = name;
 }

 public String getPid() {
    return pid;
 }

 public void setPid(String pid) {
    this.pid = pid;
 }


}

data傳輸類(lèi)---模擬dto

package maven.daily.test.mian.recursive;

import java.util.List;

public class DataDto {

private String id;
private String name;
private String pid;
private List<DataDto> childs;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public List<DataDto> getChilds() {
    return childs;
}

public void setChilds(List<DataDto> childs) {
    this.childs = childs;
}

public String getPid() {
    return pid;
}

public void setPid(String pid) {
    this.pid = pid;
}

@Override
public String toString() {
    return "{id:" + id + ", name:" + name + ", pid:" + pid + ", childs:" + childs + "}";
}

}

實(shí)體與傳輸轉(zhuǎn)換類(lèi)

package maven.daily.test.mian.recursive;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.BeanUtils;

public class DataConverter {

 public DataDto toDto(Data data) {
     DataDto dto = new DataDto();
     try {
        BeanUtils.copyProperties(dto, data);
     } catch (IllegalAccessException e) {
     } catch (InvocationTargetException e) {
     }
     return dto;
 }

}

模擬測(cè)試類(lèi)

package maven.daily.test.mian.recursive;

import java.util.ArrayList;
import java.util.List;

public class RecursiveMain {

  public static void main(String[] args) {
    List<Data> list = new ArrayList<>();
    buildData(list);
    List<DataDto> re = dealData(list);
    re.forEach(t -> {
        System.out.println(t);
    });
  }

   private static void buildData(List<Data> list) {
      list.add(new Data("p1", "root", null));
      list.add(new Data("c111", "chid111", "c11"));
      list.add(new Data("c1", "chid1", "p1"));
      list.add(new Data("c12", "chid12", "c1"));
      list.add(new Data("c13", "chid13", "c1"));
      list.add(new Data("c112", "chid112", "c11"));
      list.add(new Data("c113", "chid113", "c11"));
      list.add(new Data("c2", "chid2", "p1"));
      list.add(new Data("c3", "chid3", "p1"));
      list.add(new Data("c4", "chid4", "p1"));
      list.add(new Data("c11", "chid11", "c1"));
      list.add(new Data("c21", "chid21", "c2"));
      list.add(new Data("c22", "chid22", "c2"));
  }

   private static List<DataDto> dealData(List<Data> list) {
      List<DataDto> result = new ArrayList<DataDto>();
      List<Data> root = new ArrayList<Data>();
      list.forEach(data -> {
          if (null == data.getPid()) {
              root.add(data);
          }
      });
      DataConverter dataConverter = new DataConverter();
      root.forEach(data -> {
          result.add(Recursive(dataConverter.toDto(data), list));
      });
      return result;
  }  

  private static DataDto Recursive(DataDto dto, List<Data> datas) {
      List<DataDto> childs = new ArrayList<DataDto>();
      DataConverter dataConverter = new DataConverter();
      datas.forEach(t -> {
          if (t.getPid() != null && t.getPid().equals(dto.getId())) {
              DataDto temp = dataConverter.toDto(t);
              childs.add(temp);
              Recursive(temp, datas);
          }
      });
      dto.setChilds(childs);
      return dto;
   }

}

運(yùn)行結(jié)果

 {
id: p1,
name: root,
pid: null,
childs: [{
    id: c1,
    name: chid1,
    pid: p1,
    childs: [{
        id: c12,
        name: chid12,
        pid: c1,
        childs: []
    }, {
        id: c13,
        name: chid13,
        pid: c1,
        childs: []
    }, {
        id: c11,
        name: chid11,
        pid: c1,
        childs: [{
            id: c111,
            name: chid111,
            pid: c11,
            childs: []
        }, {
            id: c112,
            name: chid112,
            pid: c11,
            childs: []
        }, {
            id: c113,
            name: chid113,
            pid: c11,
            childs: []
        }]
    }]
}, {
    id: c2,
    name: chid2,
    pid: p1,
    childs: [{
        id: c21,
        name: chid21,
        pid: c2,
        childs: []
    }, {
        id: c22,
        name: chid22,
        pid: c2,
        childs: []
    }]
}, {
    id: c3,
    name: chid3,
    pid: p1,
    childs: []
}, {
    id: c4,
    name: chid4,
    pid: p1,
    childs: []
}]
}

到這兒就完成了利用遞歸構(gòu)造數(shù)型結(jié)構(gòu)數(shù)據(jù)天揖。

內(nèi)容講解

概念:
1.實(shí)體類(lèi) - 與持久層字段對(duì)應(yīng)
2.數(shù)據(jù)傳輸類(lèi)-根據(jù)業(yè)務(wù)需求構(gòu)造返回滿足前端展示需要的數(shù)據(jù)結(jié)構(gòu)類(lèi),另外還有屏蔽特殊字段功能跪帝。
3.轉(zhuǎn)換類(lèi)-實(shí)現(xiàn)實(shí)體類(lèi)向數(shù)據(jù)傳輸類(lèi)轉(zhuǎn)換的功能今膊。

核心

遞歸的核心:自己調(diào)用自己;結(jié)束條件伞剑。

重點(diǎn)理解


image.png
遞歸原理

第一:每一級(jí)的函數(shù)調(diào)用都有它自己的變量斑唬。
第二:每一次函數(shù)調(diào)用都會(huì)有一次返回,并且是某一級(jí)遞歸返回到調(diào)用它的那一級(jí)纸泄,而不是直接返回到main()函數(shù)中的初始調(diào)用部分赖钞。
第三:遞歸函數(shù)中,位于遞歸調(diào)用前的語(yǔ)句和各級(jí)被調(diào)函數(shù)具有相同的執(zhí)行順序聘裁。
第四:遞歸函數(shù)中雪营,位于遞歸調(diào)用后的語(yǔ)句的執(zhí)行順序和各個(gè)被調(diào)函數(shù)的順序相反。
第五:雖然每一級(jí)遞歸都有自己的變量衡便,但是函數(shù)代碼不會(huì)復(fù)制献起。
第六:遞歸函數(shù)中必須包含終止遞歸的語(yǔ)句。

遞歸性能

一個(gè)2000左右條數(shù)據(jù)镣陕,一條sql全部查出來(lái)谴餐,利用遞歸構(gòu)造深度為4的樹(shù)形結(jié)構(gòu),還是秒出呆抑。
這個(gè)秒出是指后臺(tái)運(yùn)算岂嗓,不計(jì)傳輸時(shí)間。


image.png

image.png
遞歸優(yōu)化
  1. 最經(jīng)典的斐波那契數(shù)列
  2. 尾遞歸
  3. 利用緩存
結(jié)語(yǔ)

本文目的只是拋磚引玉鹊碍。文章多處都是蜻蜓點(diǎn)水厌殉。要想更好的掌握并熟練運(yùn)用,還需多練侈咕,多體會(huì)公罕,多結(jié)合其他方面的知識(shí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耀销,一起剝皮案震驚了整個(gè)濱河市楼眷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖罐柳,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掌腰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡张吉,警方通過(guò)查閱死者的電腦和手機(jī)辅斟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)芦拿,“玉大人,你說(shuō)我怎么就攤上這事查邢≌崞椋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵扰藕,是天一觀的道長(zhǎng)缓苛。 經(jīng)常有香客問(wèn)我,道長(zhǎng)邓深,這世上最難降的妖魔是什么未桥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮芥备,結(jié)果婚禮上冬耿,老公的妹妹穿的比我還像新娘。我一直安慰自己萌壳,他們只是感情好亦镶,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著袱瓮,像睡著了一般缤骨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尺借,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天绊起,我揣著相機(jī)與錄音,去河邊找鬼燎斩。 笑死虱歪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘫里。 我是一名探鬼主播实蔽,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼谨读!你這毒婦竟也來(lái)了局装?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铐尚,沒(méi)想到半個(gè)月后拨脉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宣增,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年玫膀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爹脾。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡帖旨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出灵妨,到底是詐尸還是另有隱情解阅,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布泌霍,位于F島的核電站货抄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朱转。R本人自食惡果不足惜蟹地,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望藤为。 院中可真熱鬧怪与,春花似錦、人聲如沸缅疟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)窿吩。三九已至茎杂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纫雁,已是汗流浹背煌往。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留轧邪,地道東北人刽脖。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像忌愚,于是被迫代替她去往敵國(guó)和親曲管。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 計(jì)算機(jī)科學(xué)的新學(xué)生通常難以理解遞歸程序設(shè)計(jì)的概念腊徙。遞歸思想之所以困難,原因在于它非常像是循環(huán)推理(circular...
    啟明_b56f閱讀 7,332評(píng)論 0 20
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,090評(píng)論 1 32
  • 心中長(zhǎng)出一片森林-以冬 如果一切美好的事物檬某,都能在它最美好的時(shí)刻消亡...... 【心中長(zhǎng)出一片森林】 原曲:斯德...
    TaeTae璇閱讀 926評(píng)論 0 0
  • 當(dāng)我們大意時(shí)撬腾,時(shí)光流逝了。 青春不再現(xiàn)恢恼,少年不重來(lái)民傻。櫻花飄落時(shí),又有誰(shuí)在等閑场斑?莫等閑漓踢,白了少年頭,空悲...
    若水因因閱讀 213評(píng)論 0 1
  • 有效地測(cè)試時(shí)軟件質(zhì)量的重要保證漏隐。(測(cè)試除了量化指標(biāo)以外彭雾,還可以作為動(dòng)力來(lái)驅(qū)動(dòng)開(kāi)發(fā)的進(jìn)度,這就是極限編程倡導(dǎo)的測(cè)試驅(qū)...
    a4e794140953閱讀 453評(píng)論 0 0