精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

算法: 如何優雅的使用Javascript遞歸畫一棵結構樹

開發 前端 算法
簡單的說,遞歸就是函數自己調用自己,它做為一種算法在程序設計語言中廣泛應用。其核心思想是把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。一般來說,遞歸需要有邊界條件、遞歸前進階段和遞歸返回階段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。

[[376839]]

遞歸和尾遞歸

簡單的說,遞歸就是函數自己調用自己,它做為一種算法在程序設計語言中廣泛應用。其核心思想是把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。一般來說,遞歸需要有邊界條件、遞歸前進階段和遞歸返回階段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。

但是作為一個合格的程序員,我們也因該知道,遞歸算法相對常用的算法如普通循環等,運行效率較低。因此,應該盡量避免使用遞歸,除非沒有更好的算法或者某種特定情況,遞歸更為適合的時候。在遞歸調用的過程當中系統為每一層的返回點、局部量等開辟了棧來存儲,遞歸次數過多容易造成棧溢出等。

這個時候,我們就需要用到尾遞歸,即一個函數中所有遞歸形式的調用都出現在函數的末尾,對于尾遞歸來說,由于只存在一個調用記錄,所以永遠不會發生"棧溢出"錯誤。

 

  1. function factorial(n) { 
  2.   if (n === 1) return 1; 
  3.   return n * factorial(n - 1); 
  4.  
  5. factorial(5) // 120 

 

最多需要保存n個調用棧,復雜度 O(n),如果我們使用尾遞歸:

  1. function factorial(n, total = 1) { 
  2.   if (n === 1) return total; 
  3.   return factorial(n - 1, n * total); 
  4.  
  5. factorial(5) // 120 

此時只需要保存一個調用棧,復雜度 O(1) 。通過這個案例,你是否已經慢慢理解其精髓了呢?接下來我將介紹幾個常用的遞歸應用的案例,并在其后實現本文標題剖出的樹的實現。

遞歸的常用應用案例

1. 數組求和

對于已知數組arr,求arr各項之和。

 

  1. function sumArray(arr, total) { 
  2.     if(arr.length === 1) { 
  3.         return total 
  4.     } 
  5.     return sum(arr, total + arr.pop()) 
  6.  
  7. let arr = [1,2,3,4]; 
  8. sumArray(arr, arr[1]) // 10 

該方法給函數傳遞一個數組參數和初始值,也就是數組的第一項,通過迭代來實現數組求和。

2. 斐波那且數列

斐波那契數列(Fibonacci sequence),又稱黃金分割數列,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,斐波那契數列以如下被以遞推的方法定義:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)在現代物理、準晶體結構、化學等領域,斐波納契數列都有直接的應用。接下來我們用js實現一個求第n個斐波那契數的方法:

 

  1. // 斐波那契數列 
  2. function factorial1 (n) { 
  3.     if(n <= 2){ 
  4.         return 1 
  5.     } 
  6.     return factorial1(n-1) + factorial1(n-2) 
  7.  
  8. // 尾遞歸優化后 
  9. function factorial2 (n, start = 1, total = 1) { 
  10.     if(n <= 2){ 
  11.         return total 
  12.     } 
  13.     return factorial2 (n -1, total, total + start) 

由尾遞歸優化后的函數可以知道,每一次調用函數自身,都會將更新后的初始值和最終的結果傳遞進去,通過回溯來求得最終的結果。

3. 階乘

階乘在上文以提到過,如想回顧,請向上翻閱。

4. 省市級聯多級聯動

省市級聯多級聯動的方法本質是生成結構化的數據結構,在element或antd中都有對應的實現,這里就不做過多介紹了。

5. 深拷貝

深拷貝的例子大家也已經司空見慣了,這里只給出一個簡單的實現思路:

 

  1. function clone(target) { 
  2.    if (typeof target === 'object') { 
  3.        let cloneTarget = Array.isArray(target) ? [] : {}; 
  4.        for (const key in target) { 
  5.            cloneTarget[key] = clone(target[key]); 
  6.        } 
  7.        return cloneTarget; 
  8.    } else { 
  9.        return target; 
  10.    } 
  11. }; 

6. 爬梯問題

一共有n個臺階,每次只能走一個或兩個臺階,問要走完這個臺階,一共有多少種走法。

 

  1. n =1; result = 1  --> 1 
  2. n =2; result = 2  --> 11 2 
  3. n =3; result = 3  --> 111 12 21 
  4. ... 
  5. 如果第一步走1個臺階,由以上規律可以發現剩下的臺階有n-1種走法; 
  6. 如果第一步走2個臺階,由以上規律可以發現剩下的臺階有n-2種走法; 
  7. 則一共有fn(n-1) + fn(n-2) 種走法 
  8. function steps(n) { 
  9.     if(n <= 1) { 
  10.         return 1 
  11.     } 
  12.     return steps(n-1) + steps(n-2) 

7. 對象數據格式化

這道題是本人曾經面試阿里的一道筆試題,問題是如果服務器返回了嵌套的對象,對象鍵名大小寫不確定,如果統一讓鍵名小寫。

 

  1. let obj = { 
  2.     a: '1'
  3.     b: { 
  4.         c: '2'
  5.         D: { 
  6.             E: '3' 
  7.         } 
  8.     } 
  9. 轉化為如下: 
  10. let obj = { 
  11.     a: '1'
  12.     b: { 
  13.         c: '2'
  14.         d: { 
  15.             e: '3' 
  16.         } 
  17.     } 
  18.  
  19. // 代碼實現 
  20. function keysLower(obj) { 
  21.     let reg = new RegExp("([A-Z]+)""g"); 
  22.     for (let key in obj) { 
  23.         if (obj.hasOwnProperty(key)) { 
  24.             let temp = obj[key]; 
  25.             if (reg.test(key.toString())) { 
  26.                 // 將修改后的屬性名重新賦值給temp,并在對象obj內添加一個轉換后的屬性 
  27.                 temp = obj[key.replace(reg, function (result) { 
  28.                     return result.toLowerCase() 
  29.                 })] = obj[key]; 
  30.                 // 將之前大寫的鍵屬性刪除 
  31.                 delete obj[key]; 
  32.             } 
  33.             // 如果屬性是對象或者數組,重新執行函數 
  34.             if (typeof temp === 'object' || Object.prototype.toString.call(temp) === '[object Array]') { 
  35.                 keysLower(temp); 
  36.             } 
  37.         } 
  38.     } 
  39.     return obj; 
  40. }; 

具體過程和思路在代碼中已經寫出了注釋,感興趣可以自己研究一下。

8. 遍歷目錄/刪除目錄

我們這里使用node來實現刪除一個目錄,用現有的node API確實有刪除目錄的功能,但是目錄下如果有文件或者子目錄,fs.rmdir && fs.rmdirSync 是不能將其刪除的,所以要先刪除目錄下的文件,最后再刪除文件夾。

 

  1. function deleteFolder(path) { 
  2.     var files = []; 
  3.     if(fs.existsSync(path)) { // 如果目錄存在 
  4.         files = fs.readdirSync(path); 
  5.         files.forEach(function(file,index){ 
  6.             var curPath = path + "/" + file; 
  7.             if(fs.statSync(curPath).isDirectory()) { // 如果是目錄,則遞歸 
  8.                 deleteFolder(curPath); 
  9.             } else { // 刪除文件 
  10.                 fs.unlinkSync(curPath); 
  11.             } 
  12.         }); 
  13.         fs.rmdirSync(path); 
  14.     } 

9. 繪制分形圖形

通過遞歸,我們可以在圖形學上有更大的自由度,但是請記住,并不是最好的選擇。


我們可以借助一些工具和遞歸的思想,實現如上的分形圖案。

 10. 扁平化數組Flat

數組拍平實際上就是把一個嵌套的數組,展開成一個數組,如下案例:

 

  1. let a = [1,2,3, [1,2,3, [1,2,3]]] 
  2. // 變成 
  3. let a = [1,2,3,1,2,3,1,2,3] 
  4. // 具體實現 
  5. function flat(arr = [], result = []) { 
  6.     arr.forEach(v => { 
  7.         if(Array.isArray(v)) { 
  8.             result = result.concat(flat(v, [])) 
  9.         }else { 
  10.             result.push(v) 
  11.         } 
  12.     }) 
  13.     return result 
  14.  
  15. flat(a) 

當然這只是筆者實現的一種方式,更多實現方式等著你去探索。

用遞歸畫一棵自定義風格的結構樹

通過上面的介紹,我想大家對遞歸及其應用已經有一個基本的概念,接下來我將一步步的帶大家用遞歸畫一棵結構樹。效果圖:

 

該圖形是根據目錄結構生成的目錄樹圖,在很多應用場景中被廣泛使用,接下來我們就來看看他的實現過程吧:

 

  1. const fs = require('fs'
  2. const path = require('path'
  3. // 遍歷目錄/生成目錄樹 
  4. function treeFolder(path, flag = '|_') { 
  5.     var files = []; 
  6.      
  7.     if(fs.existsSync(path)) { 
  8.         files = fs.readdirSync(path); 
  9.         files.forEach(function(file,index){ 
  10.             var curPath = path + "/" + file; 
  11.             if(fs.statSync(curPath).isDirectory()) { // recurse 
  12.                 // obj[file] = treeFolder(curPath, {}); 
  13.                 console.log(flag, file) 
  14.                 treeFolder(curPath, '   ' + flag) 
  15.             } else { 
  16.                 // obj['--'] = file 
  17.                 console.log(flag, file) 
  18.             } 
  19.         }) 
  20.         // return obj 
  21.     } 
  22.  
  23. treeFolder(path.resolve(__dirname, './test')) 

test為我們建的測試目錄,如下:

 

我們通過短短10幾行代碼就實現了一個生成結構樹的小應用,是不是感覺遞歸有點意思呢?在這個函數中,第一個參數是目錄的絕對路徑,第二個是標示符,標示符決定我們生成的樹枝的樣式,我們可以自定義不同的樣式。

 

責任編輯:姜華 來源: 趣談前端
相關推薦

2011-08-01 13:51:31

Web

2021-06-04 07:55:05

MySQLB+ 樹數據

2021-09-06 10:38:50

二叉搜索樹遞歸

2018-04-12 11:20:16

MySQLmybatisJava

2022-03-31 08:15:59

遞歸代碼非遞歸

2024-06-11 08:32:37

JavaScrip隨機樹UI

2021-05-21 08:31:09

數據結構二叉樹

2018-03-07 16:53:25

EBG業務技術

2014-04-04 11:14:18

JavaScriptStack遞歸

2023-12-05 07:26:21

Golang項目結構

2017-07-26 11:32:50

NETRabbitMQ系統集成

2015-11-26 10:53:45

LinuxWindowsMac OS

2021-02-24 07:46:20

數據結構二叉樹

2021-09-15 07:40:50

二叉樹數據結構算法

2024-01-15 07:42:37

Figma協同編輯算法

2017-12-12 14:26:16

數據庫PostgreSQL邏輯優化

2019-09-20 15:47:24

代碼JavaScript副作用

2023-06-16 09:08:39

ReactContextRFC

2013-10-16 15:57:39

數組二叉樹

2021-07-12 15:35:56

JavaScript代碼運算符
點贊
收藏

51CTO技術棧公眾號

中文字幕免费国产精品| 欧亚洲嫩模精品一区三区| 亚洲自拍小视频免费观看| 日韩激情一区二区三区| 亚洲婷婷伊人| 91麻豆精品国产91久久久更新时间| 人妻无码一区二区三区四区| 欧美美女搞黄| 国产精品1区2区| 国产精品777| 久草视频免费在线| 国产精品亚洲人成在99www| 91精品国产手机| 日韩av资源在线| 国产成人无吗| 中文字幕av在线一区二区三区| 成人免费观看网站| 夜夜躁很很躁日日躁麻豆| 在线日韩欧美| 日韩在线观看av| 人妻体内射精一区二区| 亚洲精品aⅴ| 欧美日韩中文一区| 精品人妻一区二区三区四区在线| 黄色在线免费| 国产女主播在线一区二区| 含羞草久久爱69一区| 国产精品久久久久毛片| 三级成人在线视频| 国产最新精品视频| 永久免费看黄网站| 97视频热人人精品免费| 亚洲日本成人网| 男男做爰猛烈叫床爽爽小说| 136福利精品导航| 欧美精品一级二级| 成人3d动漫一区二区三区| 成人一级福利| 亚洲第一成年网| 男女裸体影院高潮| 超碰免费公开在线| 中文字幕日韩一区| 日韩理论片在线观看| 天堂av中文在线资源库| 国产91在线看| 97在线资源站| www.精品视频| 国产91丝袜在线18| 99re在线观看视频| 丰满人妻熟女aⅴ一区| 国产成人免费xxxxxxxx| 亚洲精品免费在线视频| 国产精品无码专区av免费播放| 麻豆精品一区二区| 91九色国产视频| 国产高潮在线观看| 国产精品77777竹菊影视小说| 成人在线中文字幕| 国产国语亲子伦亲子| 国产麻豆视频精品| 国产99视频精品免费视频36| 成人免费视频国产| 99久久精品一区| 欧美日韩在线一区二区三区| 久久99久久| 中文字幕乱码亚洲精品一区| 亚洲视频在线观看日本a| 2021av在线| 亚洲欧美一区二区不卡| 欧美激情亚洲天堂| 涩涩涩在线视频| 91久久国产综合久久| 国产一级做a爰片久久| 四虎国产精品免费久久| 日韩欧美国产精品| 超碰97人人干| 日韩综合网站| 欧美日韩ab片| 国产精品va无码一区二区三区| 日韩国产在线观看一区| 91美女片黄在线观看游戏| 亚洲va欧美va| 国产亚洲精品资源在线26u| 一区二区精品免费视频| 免费男女羞羞的视频网站在线观看| 激情亚洲一区二区三区四区| 波多野结衣天堂| 日本一区二区三区电影免费观看| 亚洲电影中文字幕| 久久午夜福利电影| 欧美国产另类| 国产精品99导航| 精品久久无码中文字幕| 久久日一线二线三线suv| 制服丝袜综合日韩欧美| 超碰激情在线| 91麻豆精品国产91久久久资源速度 | 激情av中文字幕| 一道在线中文一区二区三区| 久久精品99久久久久久久久| 99免费在线观看| 美女一区二区三区| 精品一区二区三区自拍图片区| 午夜免费播放观看在线视频| 婷婷丁香激情综合| 波多野结衣在线免费观看| 九九综合九九| 欧美精品www在线观看| 成人黄色片在线观看| 懂色av一区二区三区蜜臀| 亚洲黄色成人久久久| 国内激情视频在线观看| 91精品麻豆日日躁夜夜躁| 中文字幕免费高清| 亚洲经典自拍| 51精品国产人成在线观看| 国产精品免费播放| 精品久久久久久亚洲精品| 女人扒开腿免费视频app| 精品国产一区二区三区噜噜噜 | 国产91av视频在线观看| 蜜桃av.网站在线观看| 91精品国产麻豆| 五月天免费网站| 日韩精品久久久久久| 精品一区二区视频| 丁香花在线高清完整版视频| 日韩一区二区中文字幕| 成人做爰视频网站| 免费在线一区观看| 日韩电影在线播放| 欧美xxx性| 亚洲毛片在线看| 影音先锋亚洲天堂| 99精品久久只有精品| 免费看日本黄色| 亚洲精品一区二区三区中文字幕| 久久激情五月丁香伊人| 一级黄色大片网站| 国产精品视频看| 手机视频在线观看| 日韩av在线播放网址| 国产精品免费久久久久久| 国外av在线| 欧美性视频一区二区三区| 精品无人区无码乱码毛片国产 | 中文字幕在线视频精品| 首页国产精品| 91精品在线影院| 4438x成人网全国最大| 日韩午夜电影av| 欧美精品videos极品| 成人午夜精品在线| 久久久久久久久久网| 日本妇女一区| 国产精品mp4| 91在线导航| 日韩一卡二卡三卡四卡| 九九热国产精品视频| 成人免费视频一区二区| 日本午夜激情视频| 自拍视频一区| 国产男人精品视频| 中文字幕在线三区| 欧美精品一区二区不卡| www.毛片.com| 中文字幕乱码一区二区免费| 中文字幕一区二区在线观看视频| 国产精品草草| 美女一区视频| 97色婷婷成人综合在线观看| 欧美第一淫aaasss性| 天堂网在线播放| 在线观看日韩一区| 亚洲av无码一区二区三区在线| 成人午夜激情影院| 中文字幕无码不卡免费视频| 91精品久久久久久久久久不卡| 成人区精品一区二区| 日韩成人动漫| 精品中文字幕视频| 欧洲一区av| 欧美一级欧美三级| 好看的av在线| 伊人开心综合网| 91精品人妻一区二区三区蜜桃欧美| 久久精品国产久精国产爱| 久久人人爽人人爽人人av| 国产成人黄色| 国产精品一码二码三码在线| 中文字幕系列一区| 欧美—级a级欧美特级ar全黄| 久久精品a一级国产免视看成人 | 国产精品一区专区欧美日韩| 中文在线手机av| 亚洲偷欧美偷国内偷| www.成人在线观看| 欧美视频在线播放| 国产视频91在线| 亚洲欧洲精品一区二区精品久久久 | 亚洲天堂影视av| 丰满岳乱妇国产精品一区| 欧美性猛交xxxxxx富婆| 国产精品不卡av| 1024成人网| 欧洲av一区二区三区| 国产aⅴ精品一区二区三区色成熟| 日本在线观看免费视频| 国产日韩一区| 男人的天堂avav| 日本激情一区| 欧美日韩精品免费观看| 6080成人| 亚洲最大福利视频网站| 欧美三级电影网址| 国产成人精品亚洲精品| 欧亚在线中文字幕免费| 欧美激情女人20p| 毛片av在线| 中文字幕亚洲国产| 精品999视频| 精品亚洲一区二区三区在线观看| 不卡的日韩av| 91麻豆精品国产91久久久久久| 国产午夜无码视频在线观看 | 中文幕一区二区三区久久蜜桃| 久久福利小视频| 丰满白嫩尤物一区二区| 一级黄色高清视频| 国产精品一区二区无线| 日韩高清第一页| 久久国产尿小便嘘嘘| 国产主播中文字幕| 日本成人超碰在线观看| 无人在线观看的免费高清视频 | 91精品国产精品| 俄罗斯一级**毛片在线播放| 欧美极品第一页| xxxx成人| 97av视频在线| 性欧美18~19sex高清播放| 97碰碰碰免费色视频| 超级白嫩亚洲国产第一| 国产91精品久| 最新欧美色图| 国产精品91在线观看| 日韩另类视频| 国产精品一区二区女厕厕| 日韩在线你懂得| 亚洲精品欧美极品| 精品午夜电影| 欧美另类一区| 大胆日韩av| 亚洲综合激情五月| 欧美在线播放| 欧美成人三级在线视频| 香蕉久久国产| 亚洲一级免费观看| 国产一区不卡视频| 日本精品一二三| 99国产精品久久久| 国产高潮呻吟久久| 国产精品不卡视频| 九九热精品免费视频| 天天av天天翘天天综合网 | 亚洲精品久久7777777| 麻豆av电影在线观看| 色妞在线综合亚洲欧美| 超碰在线免费播放| 2021久久精品国产99国产精品| 精品3atv在线视频| 成人网中文字幕| 成人在线视频你懂的| 欧美一级日本a级v片| 91麻豆精品国产91久久久平台| 妞干网这里只有精品| 亚洲视频播放| 亚洲va综合va国产va中文| 国产不卡视频在线播放| 公侵犯人妻一区二区三区| 亚洲天堂成人在线观看| 日韩欧美亚洲视频| 欧美图片一区二区三区| 东京干手机福利视频| 在线观看日韩av| 超碰97国产精品人人cao| 国产成人精品日本亚洲| 91九色鹿精品国产综合久久香蕉| 欧美亚洲丝袜| 欧美午夜精品| 三年中国国语在线播放免费| 国产成人一区在线| 欧洲av一区二区三区| 亚洲永久精品国产| 中文字幕有码视频| 亚洲国产精品电影| 国产婷婷视频在线| 日韩av色在线| 黑色丝袜福利片av久久| 在线国产伦理一区| 久久激情视频| 无码成人精品区在线观看| 国产精品毛片大码女人| 国产成人亚洲欧洲在线| 6080国产精品一区二区| 理论视频在线| 7777kkkk成人观看| 日本成人精品| 一区视频二区视频| 久久精品一区| 制服丝袜在线第一页| 亚洲图片你懂的| 中文人妻熟女乱又乱精品| 亚洲精品99久久久久| 日韩精品亚洲人成在线观看| 国产在线不卡精品| 欧美日韩精品一区二区视频| koreanbj精品视频一区| 国产成人av福利| 国产成人久久久久| 欧美狂野另类xxxxoooo| av在线天堂| 国产成人鲁鲁免费视频a| 神马久久影院| 欧美 日韩 激情| 不卡在线观看av| 精品小视频在线观看| 欧美一区二区三区免费大片| 日本在线免费播放| 国产精品一区=区| 奇米影视亚洲| www.超碰com| 欧美国产在线观看| www.亚洲激情| 一本一道久久a久久精品逆3p| 蜜臀国产一区| 日韩精品一线二线三线| 日韩国产精品久久| 青娱乐国产视频| 欧美性猛片xxxx免费看久爱| 成人午夜电影在线观看| 国产精品久久久久久久久久99| 蜜臀av免费一区二区三区| 欧美韩国日本在线| 久久久久久9999| 国产美女www| 中文字幕在线成人| 欧美视频精品| 性生活免费观看视频| 国产高清在线精品| 精品无码久久久久| 日韩激情在线视频| 色香欲www7777综合网| 手机成人在线| 国产自产高清不卡| 久久久久久免费观看| 亚洲国产精品va在线看黑人| 理论片午夜视频在线观看| 久久久久久高清| 免费成人av资源网| 国产一二三四区| 亚洲电影免费观看高清完整版在线| freexxx性亚洲精品| 免费看成人av| 另类人妖一区二区av| 高h视频免费观看| 亚洲黄色在线看| 8av国产精品爽爽ⅴa在线观看| 亚洲一区二区不卡视频| 国产mv日韩mv欧美| 亚洲婷婷综合网| 久久精品99久久久久久久久| 最新国产一区二区| 国产日韩成人内射视频| 综合电影一区二区三区| 天天综合网天天综合| 国产精品久久久久久久久粉嫩av | 久热精品在线视频| 国产精品欧美大片| 91在线视频观看免费| 亚洲免费高清视频在线| 天堂av中文在线资源库| 成人免费黄色网| 香蕉av777xxx色综合一区| 美国一级片在线观看| 日韩大片在线观看视频| 四虎影视成人精品国库在线观看| 欧美极品少妇无套实战| 日本一区二区三区高清不卡 | 亚洲最新av在线网站| 欧州一区二区三区| 粉嫩虎白女毛片人体| 一级日本不卡的影视| 国产女人在线观看| 国产麻豆日韩| 久久av资源站| 成人免费毛片男人用品| 欧美国产第二页| 久久综合成人| 受虐m奴xxx在线观看|