JAVA_链表转换为树

 

1)链表List中元素为Element:

         a, 每个元素有一个自己的orgId; 

         b 指向父亲的parentOrgId;

         c,孩子链表 chilren,链表中为空

         详细的数据成员见文末的类Element

 

2) 目的: 将List中存在父节点的节点 放到它节点的孩子链表chilren中

3)收获或注意点:

      a) 在list中 用foreach循环时很难在当前list中做增删,一个好的方法是使用迭代器;

      b)  java中非原始类型的数据 在参数传递时是引用,而非副本拷贝,所以可以在子函数中修改数据

      c) 性能提升

   

方法1: 重复循环遍历链表List,将元素加入到它的父亲下,并在List中删除。

              初始状态:第一层包含List中所有元素

              结束条件:链表List中节点不再变化

              时间复杂度:o( n~2) 且有递归

 

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

//将一层排列的List 转换为具有多层树形结构的List
public class TreeFromList {
		
	TreeFromList(){	
	}
	
	Boolean changeList( List<Element>  elist, Element element ){	
		if(elist == null)  return false;	
		for( Element temp : elist){		
			//如果元素父节点指向自己,会把自己删除
			//这句很重要
			if(temp.equals(element)) continue;
			
			if(element.getParentOrgId() ==  temp.getOrgId()){				
				if(temp.getChildren()!=null){
					temp.getChildren().add(element);
				}
				else {
					List<Element> children = new ArrayList<Element>();
					children.add(element);
					temp.setChildren(children);
				}
				return true;
			}	
			else if(temp.getChildren()!=null){
				//在该节点的孩子节点中查找				
				Boolean bool=changeList(temp.getChildren(), element);
				if(bool)  return true;
			}
		}
		return false;
	}	
	public List<Element> convertList( List<Element>  elist){
		
		if(elist == null)  return null;
		
		int oldlength = elist.size();
		int newlength = oldlength-1;		
		while( oldlength > newlength )
		{
			oldlength = newlength;
			
			Iterator<Element> it = elist.iterator();
			while(it.hasNext()){
				Element temp = it.next();
					
				Boolean bool=changeList( elist, temp);
				if(bool){
					System.out.println("temp =" + String.valueOf(temp.getOrgId()));
					it.remove();
				}
			}
			newlength = elist.size();
		}
		
		return elist;
	}
	void print(List<Element> elist ){
		
		for(Element e:elist){
			
		System.out.println("id="+String.valueOf(e.getOrgId())+ "; parentID="+String.valueOf(e.getParentOrgId()) );
			if(e.getChildren()!= null) {
				print(e.getChildren());
			}
		}
	}
	
	public static void main(String[] args){
		
		TreeFromList tree = new TreeFromList();
		 List<Element> elist = new  ArrayList<Element>();
		 Element e1= new Element(0,0) ; elist.add(e1);
		 Element e2= new Element(1,0) ; elist.add(e2);
		 Element e3= new Element(2,1) ; elist.add(e3);
		 Element e4= new Element(3,2) ; elist.add(e4);
		 Element e5= new Element(4,2) ; elist.add(e5);
		 Element e6= new Element(5,1) ; elist.add(e6);
		 Element e7= new Element(6,2) ; elist.add(e7);
		 Element e8= new Element(7,3) ; elist.add(e8);
		 Element e9= new Element(8,1) ; elist.add(e9);
		 Element e10= new Element(9,0) ; elist.add(e10);
		 elist = tree.convertList(elist);		 
		 System.out.println("length =" + elist.size());
		 tree.print(elist);
	}
}

 

方法2: 在有用户交互的情况下,用户点击一个节点会在后台数据库中显示该节点的所有孩子节点

              初始状态:数据放在数据库表中

              获取条件:用户点击,多次查询,

              优势:没用缓存,速度快

              不足: 查询后台数据库较多

 

	//直接在数据库中找孩子
	//方法3: 指定顶层节点为 父亲节点,每次都查表,从上往下生成树
	public List<Element> getOrgChildrenByOrgId( Context ctx) throws Exception{
		
		List<Element> orgListRoot=null;
		
		//数据库中获取顶层节点
		orgListRoot = orgService.getOrgRoot();
		//根据第一层获取第二层节点			
		orgListRoot=getOrgChildren( orgListRoot);
		return orgListRoot;
	}
	
	//获取一个链表的孩子节点
	private List<Element> getOrgChildren( List<Element> orgListRoot) throws Exception{
		
		for(Element tempBean: orgListRoot){
			if(tempBean.getOrgId()==null) continue;
			//在数据库中获取节点的孩子
			children= orgService.getOrgChildrenByOrgId(tempBean.getOrgId());
			
			if(children !=null && children.isEmpty()== false){		
				tempBean.setChildren(children);				
			}
		}
		return orgListRoot;
	}

 

方法3: 重要思想,通过Map能够很快找到对应的元素

              a ,一次性读取整个链表List,并且按照parentid排序(在非读数据库情况下可以使用快排排序)得到orderList,时间复杂度为o(nlogn)

              b,根据orderList,将具有相同parentid的元素放到同一个map中得到 Map<parentid,map>, 其中子map为map<id,null>,

                                             并使用一个类型为Map<id,elment>的mapQuery 保存所有的elment,使得根据id查询elment的查询为o(1)

                                             总的时间复杂度为o(n)

              c,在数据库中或者orderList中可以得到 顶层节点链表rootList

              d,采用广度优先遍历或者深度优先遍历rootList中元素,根据parentid在Map<parentid,map>中一次直接查询到节点的所有孩子,并不断迭代

                     即可得到在o(n)时间复杂度内构成树

 

	List<Element> orgCSList= new ArrayList<Element>();
	
	public List<Element> getOrgByCollectStye(Context ctx) throws Exception{
			
		//找顶层节点
		List<Element>  orgListRoot = orgService.getOrgRoot();	

		//顶层节点保存到orgList
		for(Element ob:orgListRoot){
			orgCSList.add(ob);
			mapQuery.put(ob.getOrgId(), ob);
		}
		
		//找到根据父节点排序好的所有节点链表
		List<Element> tempOrderOrgList = orgService.getOrderOrg();

		//将具有相同父ID的节点放到一个map(pid, map(id,Element))
		Map<String, Object> tempOrderOrgMap = convertGroup(tempOrderOrgList);
	
		//生成Map树 (mapTree)和 orgList
		collectToMapTree(tempOrderOrgMap, orgCSList);		
		return orgCSList;
	}
	//第二项在第一项中收集
	private void collectToMapTree(	Map<String, Object> tempOrderOrgMap, 	
									List<Element> orgList)  	throws Exception{
		
		for (Element ob:orgList ){
			
			List<Element> children = new ArrayList<Element>();
			Map<String,Element> obMap = (Map<String, Element>)tempOrderOrgMap.get( ob.getOrgId() ); 
			//没有孩子
			if(obMap ==null || obMap.isEmpty()) {		
				continue;
			}
			else	{
				for(Map.Entry<String, Element> mapBean: obMap.entrySet()){
					children.add(mapBean.getValue());
				}					
				collectToMapTree(tempOrderOrgMap, children);				
				ob.setChildren(children);
			}	
		}
	}
	
	Map<String, Object > convertGroup(List<Element> orgList) {
		if(orgList==null || orgList.isEmpty()) return null;
		
		Map<String, Object >  tempMap= new HashMap<String, Object >();
		
		String pid =" ";	
		Map<String, Element >  newMap=null;
		for(Element ob:orgList){			
			
			//在顶层Map中就不加入
			if(mapQuery.containsKey(ob.getOrgId()) )
				continue;
			
			//如果当前节点的pid与此前节点的pid不同,则是新的子Map
			//相等则加入前面的子map中
			if(pid.equalsIgnoreCase(ob.getParentOrgId() )  == false ) {
				
				//找到新的子Map,如果旧的子Map不为空,则保存
				if(newMap != null) tempMap.put(pid, newMap);
				
				newMap = new HashMap<String,Element>();
				newMap.put(ob.getOrgId(), ob);
				pid = ob.getParentOrgId();
			}
			else{//相等则有相同的父ID
				newMap.put(ob.getOrgId(), ob);
			}
				
		}
		
		return tempMap;
		
	}


 

元素类

import java.util.List;

public class Element {
	
	private	Integer orgId;
	private Integer parentOrgId;
	private List<Element> children = null;
	
	Element(Integer orgId, Integer parentOrgId){
		this.orgId= orgId;
		this.parentOrgId = parentOrgId;
	}
	
	public void setOrgId(Integer orgId){
		this.orgId =orgId;
	}
	public Integer getOrgId(){
		return orgId;
	}
	
	
	public void setParentOrgId(Integer parentOrgId){
		this.parentOrgId =parentOrgId;
	}
	public Integer getParentOrgId(){
		return parentOrgId;
	}
	
	
	public void setChildren(List<Element> children){
		this.children =children;
	}
	public List<Element>  getChildren(){
		return children;
	}
}


 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值