欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java遞歸處理單位人員組織機(jī)構(gòu)樹方式

 更新時(shí)間:2023年08月26日 14:33:29   作者:@假裝  
這篇文章主要介紹了java遞歸處理單位人員組織機(jī)構(gòu)樹方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

什么是遞歸?

在說遞歸之前先說說棧(Stack)是什么?

一、棧(Stack)實(shí)現(xiàn)了一個(gè)后進(jìn)先出(LIFO)的數(shù)據(jù)結(jié)構(gòu)。你可以把棧理解為對(duì)象的垂直分布的棧,當(dāng)你添加一個(gè)新元素時(shí),就將新元素放在其他元素的頂部。

二、當(dāng)你從棧中取元素的時(shí)候,就從棧頂取一個(gè)元素。換句話說,最后進(jìn)棧的元素最先被取出,而遞歸算法就是利用了棧的線性結(jié)構(gòu)實(shí)現(xiàn)的。

一、遞歸算法是一種直接或間接地調(diào)用自身的算法。在計(jì)算機(jī)編寫程序中,遞歸算法對(duì)解決一大類問題是十分有效的,它往往使算法的描述簡潔而且易于理解,還可以可以把復(fù)雜的事情變得簡單。

二、遞歸算法是把問題轉(zhuǎn)化為規(guī)模縮小了的同類問題的子問題,然后遞歸調(diào)用函數(shù)(或過程)來表示問題的解。一個(gè)過程(或函數(shù))直接或間接調(diào)用自己本身,這種過程(或函數(shù))叫遞歸過程(或函數(shù))。

三、遞歸過程一般通過函數(shù)或子過程來實(shí)現(xiàn)。遞歸方法:在函數(shù)或子過程的內(nèi)部,直接或者間接地調(diào)用自己的算法。遞歸其實(shí)就是在棧內(nèi)存中不斷的加載同一個(gè)函數(shù)。

什么時(shí)候用遞歸呢?

當(dāng)一個(gè)功能被重復(fù)使用,而每一次使用該功能時(shí)的參數(shù)不確定,都由上次的功能元素結(jié)果來確定。

遞歸的注意事項(xiàng)!

一、必須有可最終達(dá)到的終止條件,否則程序?qū)⑾萑霟o窮循環(huán)出現(xiàn)棧內(nèi)2.存溢出錯(cuò)誤(StackOverflowError);

二、子問題在規(guī)模上比原問題小,或更接近終止條件;

三、子問題可通過再次遞歸調(diào)用求解或因滿足終止條件而直接求解;

四、子問題的解應(yīng)能組合為整個(gè)問題的解。

第一步首先封裝組織部門數(shù)據(jù)

public static List<Map<String, Object>> parseTree(List<Map<String, Object>> list) {
        List<Map<String, Object>> deptTreeList = new ArrayList<Map<String, Object>>(); // 拼裝好的deptTreeList
        Map<String, Object> f_idMap = new HashMap<String, Object>();
        for (int i = 0, l = list.size(); i < l; i++) {
            f_idMap.put(String.valueOf(list.get(i).get("F_ID")), list.get(i));
        }
        for (int i = 0, l = list.size(); i < l; i++) {
            Map<String, Object> map = list.get(i);
            //f_idMap存儲(chǔ)的均為F_ID為key的鍵值對(duì),如果以F_PID為key可以取出對(duì)象,則表明該元素是父級(jí)元素
            if(f_idMap.get(map.get("F_PID")) != null && (map.get("F_ID") != map.get("F_PID"))){
                //給當(dāng)前這個(gè)父級(jí)map對(duì)象中添加key為deptList的ArrayList
                if ((f_idMap.get(map.get("F_PID")) != null) && ((Map<String, Object>) f_idMap.get(map.get("F_PID"))).get("deptList") == null) {
                    ( (Map<String,Object>) f_idMap.get(map.get("F_PID")) ).put("deptList", new ArrayList<Map<String, Object>>());
                }
                Map<String, Object> tmap = (Map<String, Object>) f_idMap.get(map.get("F_PID"));
                ArrayList<Map<String, Object>> tArrayList = (ArrayList<Map<String, Object>>) tmap.get("deptList");
                tArrayList.add(list.get(i));
                //處理沒有父節(jié)點(diǎn)
            } else {
                deptTreeList.add(list.get(i));
            }
        }
        return deptTreeList;
    }

第二步寫Controller調(diào)用

如果不理解就多debug幾次看程序是如何執(zhí)行的。

@Controller
@RequestMapping("/dept")
public class DeptTreeController {
    //TODO 獲取帶人員組織部門樹形結(jié)構(gòu)
    @PostMapping("/getTreeDeptUser")
    public XmlServiceResult getTreeDeptUser() {
        XmlServiceResult result = new XmlServiceResult();
        List<Map<String, Object>> treeDeptList = new ArrayList();
        try (XmlServiceContext context = new XmlServiceContext()) {
            //獲取單位集合(這個(gè)數(shù)據(jù)就是數(shù)據(jù)庫查出來的,框架不同換成自己數(shù)據(jù)源就好)
            List deptList = DataUtil.getDataList(context, "sys_dept/getDeptList", "list");
            //拼裝單位樹形結(jié)構(gòu)
            treeDeptList = DataUtil.parseTree(deptList);
            //獲取用戶集合(這個(gè)數(shù)據(jù)就是數(shù)據(jù)庫查出來的,框架不同換成自己數(shù)據(jù)源就好)
            List userList = DataUtil.getDataList(context, "sys_user/getUserList", "userList");
            // 將單位樹和用戶集合調(diào)用tree方法進(jìn)行遞歸拼裝
            tree(treeDeptList, userList);
            result.getData().put("deptList", treeDeptList);
        }
        return result;
    }
    /*遞歸遍歷組織機(jī)構(gòu),判斷id相同填入數(shù)據(jù)*/
    public void tree(List<Map<String, Object>> deptListTree, List<Map<String, Object>> userList) {
        for (int i = 0; i < deptListTree.size(); i++) {
            Map <String,Object> deptMap = deptListTree.get(i);
            if (!CollectionUtils.isEmpty((List) deptMap.get("deptList"))) {
                List<Map<String, Object>> deptChildren = (List<Map<String, Object>>) deptMap.get("deptList");
                // 封裝有子節(jié)點(diǎn)單位的數(shù)據(jù)
                List users =new ArrayList();
                for (Map userMap : userList) {
                    if (deptMap.get("SID").equals(userMap.get("R_DEPT"))) { // 單位id(SID)和用戶表中的單位id(R_DEPT)對(duì)應(yīng)上則拼裝
                        users.add(userMap);
                    }
                }
                deptListTree.get(i).put("userList",users);
                tree(deptChildren, userList); // 如果能夠拿到單位集合說明下級(jí)還有單位則遞歸下級(jí)單位list
            } else {
                // 封裝沒有子節(jié)點(diǎn)單位數(shù)據(jù)
                List users =new ArrayList();
                for (Map userMap : userList) {
                    if (deptMap.get("SID").equals(userMap.get("R_DEPT"))) {
                        users.add(userMap);
                    }
                }
                deptListTree.get(i).put("userList",users);
            }
        }
    }
}

第三步打開postman測(cè)試一下成果

下面總結(jié)一下遞歸的優(yōu)缺點(diǎn)

遞歸好處:

  • 代碼更簡潔清晰,可讀性更好
  • 遞歸可讀性好這一點(diǎn),對(duì)于初學(xué)者可能會(huì)反對(duì)。實(shí)際上遞歸的代碼更清晰,但是從學(xué)習(xí)的角度要理解遞歸真正發(fā)生的什么,是如何調(diào)用的,調(diào)用層次和路線,調(diào)用堆棧中保存了什么,可能是不容易。但是不可否認(rèn)遞歸的代碼更簡潔。
  • 一般來說,一個(gè)人可能很容易的寫出前中后序的二叉樹遍歷的遞歸算法,要寫出相應(yīng)的非遞歸算法就比較考驗(yàn)水平了,恐怕至少一半的人搞不定。所以說遞歸代碼更簡潔明了。

遞歸壞處:

  • 由于遞歸需要系統(tǒng)堆棧,所以空間消耗要比非遞歸代碼要大很多。
  • 而且,如果遞歸深度太大,可能系統(tǒng)撐不住,所以在遞歸之前要考慮數(shù)據(jù)層級(jí)深度否則就棧內(nèi)存溢出(StackOverflowError)。

最后

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論