JSTree下的模糊查詢算法——樹結構數據層次遍歷和遞歸分治地深入應用


 A表示區域節點,S表示站點結點

 問題描述:現有jstree包含左圖中的所有結點信息(包含區域結點和站點結點),需要做到輸入站點名稱模糊查詢,顯示查詢子樹結果如右圖

 解決策略:

  1、先模糊查詢所得站點所在區域結點A5,A6,A4,根據這些從下往上搜索所有子樹的區域結點(主義表述,是區域結點),存至set集合(避免重復放入)

  2、找出set集合中的最高點A1(最高點的父節點為空),查詢結點信息放入jsonobject,從上往下搜索子樹中A1所有孩子結點(A2,A4),遞歸遍歷A2,A4的孩子結點,存至孩子結點數組,

 遇到區域結點沒有孩子結點則表示其到了最底層區域結點(A5,A6,A4),將其對應區域結點信息存至其孩子結點數組

  3、兩步遞歸操作,設值注入最高點結點信息,最終得到包含整棵子樹的所有結點信息。返回給頁面

 
         

 

if (name != null && !"".equals(name)) {
    name = new String(name.getBytes("iso-8859-1"),"utf-8"); //字符串轉碼
    StringBuffer searchValue = new StringBuffer();
    searchValue.append("%").append(name).append("%");      //模糊查詢格式化
    List<StationBase> stationBaseList = stationBaseService.findStationBaseByName(searchValue.toString());      //根據站點名稱模糊查找站點集合
    List<String> stationCodes = new ArrayList<>();      //裝填上面模糊查詢中所負責的站點code,
    List<Integer> areaIds_bottom = new ArrayList<>();     //存放上面站點所在區域id,即最底層的區域結點id
    Set<Integer> areaIdSet = new HashSet<Integer>();        //存放子樹中所有區域結點的id,避免重復用set集合
    for (StationBase stationBase:stationBaseList) {
        if(areaIds.contains(stationBase.getArea().getId())){    //areaIds表示用戶所負責的所有區域站點的id,即整顆樹區域節點id
            stationCodes.add(stationBase.getStationCode());
            areaIds_bottom.add(stationBase.getArea().getId());
            areaIdSet.add(stationBase.getArea().getId());
        }
    }
    areaIdSet = getAllAreaIdBySearch(areaIdSet,areaIds_bottom);     //設值注入獲取子樹中所有區域結點的id
    //找出最高點,裝入集合
    JSONObject jo_top = new JSONObject();       //最高點結點
    for(Integer area_Id : areaIdSet){
        if(area_Id!=null){
            List<Integer> area_Ids = new ArrayList<>();     //為了符合傳入的是List集合
            area_Ids.add(area_Id);
            if(stationBaseService.findParentIdsByAreaIds(area_Ids).get(0)==null) {      //找出最高點,並裝填信息
                Area area = areaService.findAllArea(area_Id).get(0);
                JSONObject state = new JSONObject();
                jo_top.put("id", areaPrefix + area.getId());
                jo_top.put("text", area.getArea());
                jo_top.put("type", "areatype");
                state.put("opened", true);
                jo_top.put("state", state);
                jo_top = findChainArea(jo_top, areaIdSet, areaPrefix, stationCodes);     //設值注入獲取包含根結點的子樹
                break;
            }
        }
    }
    jsonArray.add(jo_top);      //存入json數組
    return jsonArray;
}
/**
 * 遞歸查找包括最底層areaIdSet一直往上的所有areaId,避免重復用Set集合
 * @param areaIdSet     最底層到最高層所有層的areaId集合
 * @param areaId_row    根據用戶輸入站點名所查的最底層areaId集合
 * @return
 */
protected Set<Integer> getAllAreaIdBySearch(Set<Integer> areaIdSet,List<Integer> areaId_row){
    if(areaId_row!=null && areaId_row.size()>0 && areaId_row.get(0)!=null){      //areaId_row寫在與前面,避免為空先做判斷,直到查到ParentId為空結束遞歸
        List<Integer> areaParentIdList = stationBaseService.findParentIdsByAreaIds(areaId_row);     //獲取當前areaId_row所有的parentId
        for (Integer areaId:areaParentIdList){
            areaIdSet.add(areaId);         //使用set集合對所搜集areaId進行去重
        }
        return getAllAreaIdBySearch(areaIdSet,areaParentIdList);    //遞歸訪問上一層區域結點
    }
    return areaIdSet;
}


/**
 * 遞歸查找從最高點jo往下一層層遍歷,將遍歷結點存至孩子結點數組中
 * @param jo       最高點
 * @param areaIdSet     整顆樹區域id
 * @param areaPrefix    區域id前綴
 * @param stationCodes  子樹所有站點code
 * @return
 */
protected JSONObject findChainArea(JSONObject jo,Set<Integer> areaIdSet,String areaPrefix,List<String> stationCodes){
    List<Integer> childIds = stationBaseService.findIdsByParent(Integer.parseInt(jo.get("id").toString().split("_")[1]));
    if(childIds!=null && childIds.size()>0 && childIds.get(0)!=null){       //有子區域節點,非葉節點
        //查詢子區域節點信息,添加到jo中,areaIdSet中對應的id
        JSONArray areaChildArray = new JSONArray();     //存放該結點在對應子樹中的孩子結點數組
        for (Integer childId:childIds) {
            if(areaIdSet.contains(childId)){     //屬於子樹中結點便添加到孩子結點數組中
                Area area = areaService.findAllArea(childId).get(0);
                JSONObject jo_child = new JSONObject();
                JSONObject state = new JSONObject();
                jo_child.put("id",areaPrefix+area.getId());
                jo_child.put("text",area.getArea());
                jo_child.put("type","areatype");
                state.put("opened", true);
                jo_child.put("state",state);
                jo_child = findChainArea(jo_child,areaIdSet,areaPrefix,stationCodes);
                areaChildArray.add(jo_child);
            }
        }
        jo.put("children",areaChildArray);
    }else{      //無子區域,葉節點,添加站點信息
        List<StationBase> stationBaseList = stationBaseService.findByAreaId(Integer.parseInt(jo.get("id").toString().split("_")[1]));
        JSONArray stationArray = new JSONArray();       //該站點下的所有站點
        for (StationBase stationBase : stationBaseList){
            if(stationCodes.contains(stationBase.getStationCode())){
                JSONObject stationObj = new JSONObject();
                stationObj.put("id", "s_" + stationBase.getStationCode());
                stationObj.put("text", stationBase.getStationName());
                stationObj.put("type", "stationInfo");
                stationObj.put("children", false);
                stationArray.add(stationObj);
            }
        }
        jo.put("children",stationArray);
    }
    return jo;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM