摘要:遞歸遞歸算法在日常工作中算是用的比較多的一種,比如樹的遍歷,多層級(jí)樹狀結(jié)構(gòu)的生成,遍歷尋找某個(gè)樹節(jié)點(diǎn)等先來看下數(shù)據(jù)結(jié)構(gòu)張飛關(guān)羽劉備荀彧關(guān)平曹操貂蟬一般情況下后臺(tái)返回類似于如上的嵌套數(shù)據(jù)結(jié)構(gòu),或者說只得到一部分?jǐn)?shù)據(jù),點(diǎn)擊某個(gè)子節(jié)點(diǎn),異步加載節(jié)
遞歸
遞歸算法在日常工作中算是用的比較多的一種,比如DOM樹的遍歷,多層級(jí)樹狀結(jié)構(gòu)的生成,遍歷尋找某個(gè)樹節(jié)點(diǎn)等
1 先來看下數(shù)據(jù)結(jié)構(gòu)
var result = { id:0, name:"張飛", item:[ {id:1,name:"關(guān)羽"}, {id:2,name:"劉備",item:[ {id:5,name:"荀彧"}, {id:6,name:"關(guān)平"} ]}, {id:3,name:"曹操"}, {id:4,name:"貂蟬"}, ] }
一般情況下后臺(tái)返回類似于如上的嵌套數(shù)據(jù)結(jié)構(gòu),或者說只得到一部分?jǐn)?shù)據(jù),點(diǎn)擊某個(gè)子節(jié)點(diǎn),異步加載節(jié)點(diǎn),異步加載之后的數(shù)據(jù)可能如下:
var result = { id:0, name:"張飛", item:[ {id:1,name:"關(guān)羽"}, {id:2,name:"劉備",item:[ {id:5,name:"荀彧"}, {id:6,name:"關(guān)平"} ]}, //點(diǎn)擊曹操這一項(xiàng),加載出來劉禪和周倉,點(diǎn)擊周倉,又異步加載項(xiàng)羽和別姬 {id:3,name:"曹操",item:[ {id:8,name:"劉禪"}, {id:9,name:"周倉",item:[ {id:10,name:"項(xiàng)羽"}, {id:11,name:"別姬"} ]} ]}, {id:4,name:"貂蟬"}, ] } //點(diǎn)擊曹操,返回如下數(shù)組 [ {id:8,name:"劉禪"}, {id:9,name:"周倉"} ] //點(diǎn)擊周倉,返回如下數(shù)組 [ {id:8,name:"項(xiàng)羽"}, {id:9,name:"別姬"} ]
2 如何實(shí)現(xiàn)項(xiàng)目中的需求
以目前我做的一個(gè)react項(xiàng)目為例:需求是
將類似于這樣的數(shù)據(jù)以樹狀結(jié)構(gòu)展示出來
異步加載子節(jié)點(diǎn)的數(shù)據(jù),有可能是加載子節(jié)點(diǎn),有可能是加載同級(jí)節(jié)點(diǎn)
所以就需要定位到每次點(diǎn)擊的節(jié)點(diǎn)的位置,然后根據(jù)其他屬性判斷如何添加節(jié)點(diǎn)
關(guān)鍵就是如何通過遞歸找到對(duì)應(yīng)id的節(jié)點(diǎn)位置
我的實(shí)現(xiàn)思路就是維持一個(gè)state狀態(tài)對(duì)象,每次異步請(qǐng)求回來的數(shù)據(jù),根據(jù)返回的id來判斷點(diǎn)擊的位置(數(shù)據(jù)中所有節(jié)點(diǎn)id唯一),進(jìn)而將數(shù)據(jù)添加到state中對(duì)應(yīng)的id位置中
3 代碼實(shí)現(xiàn)遞歸
深度優(yōu)先
var item = [result] //設(shè)置一個(gè)全局的value,存放找到對(duì)應(yīng)item的時(shí)候的引用地址 var value = null ; //函數(shù)要有返回值,否則默認(rèn)返回undefiend function getName(item,id){ if(!item) return null ; for (var i = 0 ;i如果想要更加的通用一些,可以稍加優(yōu)化一下
var item = [result] function getName(item,id){ let value = null ; let ret = recurision(item,id); return ret ; function recurision(item,id){ if(!item) return null ; for (var i = 0 ;i以上代碼實(shí)現(xiàn)遞歸的核心思路是依靠聲明一個(gè)外部的變量,遞歸函數(shù)內(nèi)部進(jìn)行查找,如果找到對(duì)應(yīng)的item,則將此item賦值給value,遞歸函數(shù)返回改value值;
總感覺代碼還不夠簡(jiǎn)潔,大家有好的思路歡迎隨時(shí)交流。
上面這種方法,傳入的item是數(shù)組,當(dāng)時(shí)考慮的是傳入數(shù)組可能會(huì)方便一些;
下面這種方法傳入的rootItem是對(duì)象,感覺下面這種方法會(huì)比較好一些;
這兩者采取的遞歸方式都是深度優(yōu)先的搜索方式,通過我們記錄遞歸的執(zhí)行軌跡可以看出來;
====2017/9/20更新,地鐵上看了一些文章;優(yōu)化一下代碼;
function transerDF(rootItem,id){ var value = null ; (function recurse(currentItem){ if(currentItem == null) return null ; console.log(currentItem.id);//記錄遞歸的執(zhí)行軌跡 if(currentItem.item){ for(var i = 0 ; i < currentItem.item.length ; i++){ recurse(currentItem.item[i]) } } if(currentItem.id == id){ value = currentItem; } })(rootItem) return value ; } var ret = transerDF(result,1); console.log(ret);廣度優(yōu)先
function transerBF(rootItem,id){ var value ; var queue = [];//用數(shù)組模擬隊(duì)列 queue.push(rootItem);//放入隊(duì)列末尾 var currentItem = queue.shift();//取出隊(duì)列中的首位 while(currentItem){ console.log(currentItem.id);//記錄遞歸軌跡 if(currentItem.item){ for(var i=0;i以上分析通過記錄遞歸軌跡,我們可以很清晰的看到遞歸執(zhí)行的順序以及深度遞歸和廣度遞歸不同的實(shí)現(xiàn)思想;
jimwmg@foxmail.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/91979.html
摘要:先畫個(gè)樹,然后解釋何為深度,何為廣度第一層子集第二層子集第二層子集第三層,子集第三層第四層圖就不畫太復(fù)雜了,最高四層的結(jié)構(gòu),如果換成的形式的話可以理解成第一層第二層 先畫個(gè)樹,然后解釋 何為深度, 何為廣度 第一層 子集 | ...
簡(jiǎn)單的遍歷一個(gè)樹形結(jié)構(gòu)數(shù)據(jù)的幾種方法、非遞歸方法效率最好。 (function (window, undefined) { var treeNodes = [ { id: 1, name: 1, children: [ { i...
摘要:樹中結(jié)點(diǎn)的最大層次稱為樹的深度或高度。二叉樹有深度遍歷和廣度遍歷,深度遍歷有前序中序和后序三種遍歷方法。二叉樹的前序遍歷可以用來顯示目錄結(jié)構(gòu)等中序遍歷可以實(shí)現(xiàn)表達(dá)式樹,在編譯器底層很有用后序遍歷可以用來實(shí)現(xiàn)計(jì)算目錄內(nèi)的文件及其信息等。 樹的簡(jiǎn)介 棧、隊(duì)列、鏈表等數(shù)據(jù)結(jié)構(gòu),都是順序數(shù)據(jù)結(jié)構(gòu)。而樹是非順序數(shù)據(jù)結(jié)構(gòu)。樹型結(jié)構(gòu)是一類非常重要的非線性結(jié)構(gòu)。直觀地,樹型結(jié)構(gòu)是以分支關(guān)系定義的層次結(jié)...
摘要:一數(shù)據(jù)模型二遞歸實(shí)現(xiàn)遞歸實(shí)現(xiàn)三非遞歸廣度優(yōu)先實(shí)現(xiàn)先將第一層節(jié)點(diǎn)放入棧如果該節(jié)點(diǎn)有子節(jié)點(diǎn),繼續(xù)添加進(jìn)入棧底非遞歸廣度優(yōu)先實(shí)現(xiàn)四非遞歸深度優(yōu)先實(shí)現(xiàn)先將第一層節(jié)點(diǎn)放入棧如果該節(jié)點(diǎn)有子節(jié)點(diǎn),繼續(xù)添加進(jìn)入棧頂非遞歸深度優(yōu)先實(shí)現(xiàn) 文章來源:http://www.html-js.com/articl... 簡(jiǎn)單的遍歷一個(gè)樹形結(jié)構(gòu)數(shù)據(jù)的幾種方法、非遞歸方法效率最好。 一:數(shù)據(jù)模型: (function...
摘要:算法之深度優(yōu)先遍歷和廣度優(yōu)先遍歷背景在開發(fā)頁面的時(shí)候,我們有時(shí)候會(huì)遇到這種需求在頁面某個(gè)節(jié)點(diǎn)中遍歷,找到目標(biāo)節(jié)點(diǎn),我們正常做法是利用選擇器,或者,但在本文,我們從算法的角度去查找節(jié)點(diǎn),同時(shí)理解一下深度優(yōu)先遍歷和廣度優(yōu)先遍歷的原理。 JS算法之深度優(yōu)先遍歷(DFS)和廣度優(yōu)先遍歷(BFS) 背景 在開發(fā)頁面的時(shí)候,我們有時(shí)候會(huì)遇到這種需求:在頁面某個(gè)dom節(jié)點(diǎn)中遍歷,找到目標(biāo)dom節(jié)點(diǎn),...
閱讀 2905·2021-11-24 09:39
閱讀 1163·2021-11-02 14:38
閱讀 4156·2021-09-10 11:26
閱讀 2748·2021-08-25 09:40
閱讀 2310·2019-08-30 15:54
閱讀 482·2019-08-30 10:56
閱讀 2744·2019-08-26 12:14
閱讀 3216·2019-08-26 12:13