這是一個根據串列生成一個樹狀結構的較簡單實作,搜了搜看起來好像沒多少人總結過這種實作,寫上來整理一下自己的思路,請大家用用看看,應該用起來問題不大?反正我沒遇到BUG,
實作的時間復雜度為O(N),空間復雜度應該還是O(N)吧,不過GPT說O(1)可能是因為java的物件實作hash鏈表是參考而不是新建一個新物件?
好的,首先表明這個方法實作的前提條件:
1:串列包含的物體類必須有id和pid(也就是父類ID)兩個屬性,另外,需要重寫物體類子類串列的get方法,當串列為空時候new一個串列,(這個其實也是為了防止空指標,嫌棄麻煩的可以在下面的構造中加入判斷空串列)
2其根節點必須是0或者某個特定的數字,(為空也行,但是你得在獲取自己的父節點時判斷pid是否為空,并且給他賦值一個永遠無法用到的值,這個鍵值對應的節點子節點串列即為所需的選單樹)
這些都不太影響實作的時間復雜度,只是為了處理例外情況的解決辦法,所以可以忽略,除了那個id和pid,不過講真,一個樹結構沒這兩個屬性也挺離譜的,
廢話少說,上代碼,
首先生成無限級分類樹的代碼,串列物體類與所需物體類不同也不是大問題,
list<menuVo> nodeList = 獲得list的方法();
Hashmap<menuVO> hashMap =new Hashmap<>();
for(menuVO node : nodeList){
//添加自身節點,如果已經有自身節點代表之前遍歷過他的子類,把之前放入的子類拿出來賦給自己,再將自己放回表內,提供給后續子類使用, menuVO now = hashMap.get(node.getId()); if(now!=null){ node.setChildren(now.getChildren()); } //如果在這里過濾區分條件,無法確保節點存在,如果作為父類節點被子類創建,會存在一個沒有賦值的節點存在,且在接下來的查找父類時會將無值物件存放入父類子串列中, hashMap.put(node.getId(),node); //尋找自己的父類節點,沒有就代表父類結點未遍歷、自己創一個先用著,等到遍歷到父類節點時再由父類轉換子類物件, menuVO parent = hashMap.getOrDefault(node.getPid(),new menuVO()); //選擇條件放在這里,判斷是否需要加入node.
if(選擇判斷陳述句){
parent.getChildren().add(node);//似乎這么塞也行,但是還得存放一下父類,因為如果hashmap里沒有映射,父類塞完之后沒有用,如果hashmap記憶體在父類,shikeyi直接影響父類物件,
hashMap.put(node.getPid(),parent);
}
}
該實作具體的邏輯就是遍歷整個串列,在一個hashmap中一個結點只有兩個身份,一個是特定節點的子節點,一個是它自身節點,只要將這兩個身份實作,最后獲得的根節點,其下屬的子節點串列就是整個選單樹,不需要關心某個節點有多少子節點,只需要關心我是誰,需要放在hash表的哪里?我的父節點是誰,我需要把我放在他的子節點鏈表下,這樣可以不需要對節點進行排序,也能實作構造邏輯樹,如果有排序需求的話,,,最后的時候對其進行一下排序,不過這樣的話時間復雜度就上去了,(這里可能需要優化一下?不過賣點就是不排序直接生成啊,)
以下是寫的操作串列的工具類,這個確實是可以拿來用的,不說時間復雜度了,反正應該是最簡了吧,除非再改一改資料結構
第一獲取節點
private menuVO getByCode(List<menuVO> list, String code) { for (int i = 0; i < list.size(); i++) { menuVO vo = list.get(i); if (code.equals(vo.getCode())) {//看他自己是不是這個節點 return vo; } vo = vo.getChildren().size() > 0 ? getByCode(vo.getChildren(), code) : null; if (vo != null) { return vo; } } return null; }
第二,洗掉特定節點
private Boolean removeByCode(List<menuVO> list, String code) { for (int i = 0; i < list.size(); i++) { menuVO vo = list.get(i); if (code.equals(vo.getCode())) { list.remove(i); return true; } if (vo.getChildren().size() > 0 ? removeByCode(vo.getChildren(), code) : false) {//沒子節點就不遞回了, return true; } } return false; }
第三增加節點.那不是跟洗掉差不多?穿參不一樣罷了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555050.html
標籤:Java
上一篇:Java的泛型
下一篇:返回列表