zoukankan      html  css  js  c++  java
  • 根据数据的父子关系创建树形结构并实现遍历

      在实际开发中,有一种数据是类型,它存在父子关系,比如京东商城中,商品的分类有家用电器和服饰鞋帽,家用电器下边有大家电和家用电子,然后他们下边还有子类。而且这类父子关系有时深度是不确定的,本文用下面的方法,将所有类似分类的结点创建成一棵树并遍历打印他们。

    1.结点要实现下面的接口:

    1. package subAndsup;  
    2. import java.util.List;  
    3.   
    4. /** 
    5.  * add by ak on 2013-11-28 
    6.  */  
    7. public  interface InheritedNode<T> {  
    8.   
    9. <SPAN style="WHITE-SPACE: pre"> </SPAN>boolean isChildFrom(T node);  
    10. <SPAN style="WHITE-SPACE: pre"> </SPAN>boolean isBrother(T node);  
    11. <SPAN style="WHITE-SPACE: pre"> </SPAN>void addChildNode(T node);  
    12. <SPAN style="WHITE-SPACE: pre"> </SPAN>List<T> getChildNodes();  
    13. <SPAN style="WHITE-SPACE: pre"> </SPAN>  
    14. }  
    package subAndsup;
    import java.util.List;
    
    /**
     * add by ak on 2013-11-28
     */
    public  interface InheritedNode<T> {
    
    	boolean isChildFrom(T node);
    	boolean isBrother(T node);
    	void addChildNode(T node);
    	List<T> getChildNodes();
    	
    }
    


    2.工具类如下:

    1. package subAndsup;  
    2.   
    3. import java.util.ArrayDeque;  
    4. import java.util.ArrayList;  
    5. import java.util.Deque;  
    6. import java.util.Iterator;  
    7. import java.util.LinkedList;  
    8. import java.util.List;  
    9.   
    10. /** 
    11.  * add by ak on 2013-11-28 
    12.  */  
    13. public class TreeUtil {  
    14.       
    15.     /** 
    16.      * 将无序的结点集合,创建成一棵树。 
    17.      * 创建过程中使用了树的广度优先遍历,并且在考察无序集合的元素时, 
    18.      * 将其逐个插入到广度优先遍历结果集中,最后得到的结果集即是广度优先 
    19.      * 遍历的结果,也是从根元素(结果集中第一个元素)串联好的树形结构。 
    20.      * @param root 根元素 
    21.      * @param allCategory 无序的、不含根元素的集合 
    22.      * @return 包含子类的树形结构的根元素 
    23.      */  
    24.     public static <T extends InheritedNode> T getTree(T root, LinkedList<T> list) {  
    25.         // 模拟树的广度遍历结果的集合   
    26.         LinkedList<T> traversalList = new LinkedList<T>();  
    27.         traversalList.push(root);  
    28.         // 原始集合不为空,则继续迭代,将其中的元素加入到树的广度遍历结果集合中   
    29.         while(list.size() != 0) {  
    30.             // 迭代原始集合中的元素   
    31.             Iterator<T> iterAll = list.iterator();  
    32.             while(iterAll.hasNext()) {  
    33.                 T ndInAll = iterAll.next();  
    34.                 // 迭代树的广度遍历结果集合中的元素   
    35.                 Iterator<T> iterTrav = traversalList.iterator();  
    36.                 int indInTrav = 0;// 记录迭代当前元素的位置   
    37.                 boolean mate = false;// 标识是否找到父子类匹配关系   
    38.                 while(iterTrav.hasNext()) {  
    39.                     T ndInTrav = iterTrav.next();  
    40.                     // 如果存在父子类关系,则在在树的广度遍历结果集合中添加该元素,并父类中加入子元素   
    41.                     if(!mate) {  
    42.                         if(ndInAll.isChildFrom(ndInTrav)) {  
    43.                             // 如果存在父子类关系,则在父类中加入子元素,并设置标识   
    44.                             ndInTrav.addChildNode(ndInAll);  
    45.                             mate = true;  
    46.                         }  
    47.                     } else {  
    48.                         // 在找到iterInAll元素的父类之后,继续迭代,找到它的兄弟结点的位置   
    49.                         if(ndInAll.isBrother(ndInTrav)) {  
    50.                             break;  
    51.                         }  
    52.                     }  
    53.                     indInTrav++; // 执行++之后为迭代当前元素的位置   
    54.                 }  
    55.                 if(mate) {  
    56.                     // 如果找到iterInAll元素的父类,则在它的兄弟结点之前插入该元素   
    57.                     traversalList.add(indInTrav, ndInAll);  
    58.                     // 移除已经匹配的元素   
    59.                     iterAll.remove();  
    60.                 }  
    61.             }  
    62.         }  
    63.         // 最后将所有元素已经放到了树的广度遍历结果集合中,并且元素之间建立好了子父关系,即只取根就可得到所有元素   
    64.         T root2 = traversalList.getFirst();  
    65.         return root2;  
    66.     }  
    67.   
    68.     /** 
    69.      * 通过树的深度优先遍历获取树的遍历集合 
    70.      * @param root 树的根元素 
    71.      * @return 深度优先遍历方式的遍历集合 
    72.      */  
    73.     public static <T extends InheritedNode> List<T> createDepthFirstTraversalList(T root) {  
    74.         List<T> depthFirstTraversalList = new ArrayList<T>();  
    75.         // 深度优先遍历使用的栈结构   
    76.         Deque<T> stack = new ArrayDeque<T>();  
    77.         stack.addFirst(root);  
    78.         T node = null;  
    79.         while((node=stack.pollFirst()) != null) {  
    80.             List<T> sub = node.getChildNodes();  
    81.             if(sub != null && !sub.isEmpty()) {  
    82.                 for(int i=0; i<sub.size(); i++) {  
    83.                     stack.addFirst(sub.get(i));  
    84.                 }  
    85.             }  
    86.             depthFirstTraversalList.add(node);  
    87.         }  
    88.         return depthFirstTraversalList;  
    89.     }  
    90.       
    91.     /** 
    92.      * 通过树的广度优先遍历获取树的遍历集合 
    93.      * @param root 树的根元素 
    94.      * @return 深度优先遍历方式的遍历集合 
    95.      */  
    96.     public static <T extends InheritedNode> List<T> createBreadthFirstTraversalList(T root) {  
    97.         List<T> depthFirstTraversalList = new ArrayList<T>();  
    98.         // 广度优先遍历使用的队列结构   
    99.         Deque<T> stack = new ArrayDeque<T>();  
    100.         stack.addLast(root);  
    101.         T node = null;  
    102.         while((node=stack.pollFirst()) != null) {  
    103.             List<T> sub = node.getChildNodes();  
    104.             if(sub != null && !sub.isEmpty()) {  
    105.                 for(int i=0; i<sub.size(); i++) {  
    106.                     stack.addLast(sub.get(i));  
    107.                 }  
    108.             }  
    109.             depthFirstTraversalList.add(node);  
    110.         }  
    111.         return depthFirstTraversalList;  
    112.     }  
    113.       
    114.     /** 
    115.      * 打印树形结构,打印部分可以根据业务需求进行修改 
    116.      * @param root 树的根元素 
    117.      */  
    118.     public static <T extends InheritedNode> void printTreeByDepthFirstTraversal(T root) {  
    119.         List<T> depthFirstTraversalList = createDepthFirstTraversalList(root);  
    120.         System.out.println(depthFirstTraversalList<SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif"></SPAN><SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">);</SPAN>  
    121.         // 记录每个元素的深度   
    122.         int[] deepList = new int[depthFirstTraversalList.size()];  
    123.         System.out.printf("%-5s", root);  
    124.         int deep = 1; // 考察的当前元素的深度   
    125.         deepList[0] = 1;  
    126.         for(int i=1; i<depthFirstTraversalList.size(); i++) {  
    127.             if(depthFirstTraversalList.get(i).isChildFrom(depthFirstTraversalList.get(i-1))) {  
    128.                 // 如果判断成立,则深度加1   
    129.                 deep++;  
    130.                 deepList[i] = deep;  
    131.                 // 如果上一个元素是当前元素的父亲,则打印   
    132.                 System.out.printf("%-5s", depthFirstTraversalList.get(i));  
    133.             } else {  
    134.                 // 如果上一个元素不是当前元素的父亲,则回溯迭代找到当前元素的父亲,换行进行打印   
    135.                 System.out.println();  
    136.                 for(int j=i-2; j>=0; j--) {  
    137.                     if(depthFirstTraversalList.get(i).isChildFrom(depthFirstTraversalList.get(j))) {  
    138.                         deep = deepList[j] + 1;  
    139.                         deepList[i] = deep;  
    140.                         // 当前元素之前用空进行打印,在此利用了元素的深度   
    141.                         for(int k=0; k<deep-1; k++) {  
    142.                             System.out.printf("%-5s", "");  
    143.                         }  
    144.                         System.out.printf("%-5s", depthFirstTraversalList.get(i));  
    145.                         break;  
    146.                     }  
    147.                 }  
    148.             }  
    149.         }  
    150.         System.out.println();  
    151.     }  
    152.       
    153. }  
    package subAndsup;
    
    import java.util.ArrayDeque;
    import java.util.ArrayList;
    import java.util.Deque;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * add by ak on 2013-11-28
     */
    public class TreeUtil {
    	
    	/**
    	 * 将无序的结点集合,创建成一棵树。
    	 * 创建过程中使用了树的广度优先遍历,并且在考察无序集合的元素时,
    	 * 将其逐个插入到广度优先遍历结果集中,最后得到的结果集即是广度优先
    	 * 遍历的结果,也是从根元素(结果集中第一个元素)串联好的树形结构。
    	 * @param root 根元素
    	 * @param allCategory 无序的、不含根元素的集合
    	 * @return 包含子类的树形结构的根元素
    	 */
    	public static <T extends InheritedNode> T getTree(T root, LinkedList<T> list) {
    		// 模拟树的广度遍历结果的集合
    		LinkedList<T> traversalList = new LinkedList<T>();
    		traversalList.push(root);
    		// 原始集合不为空,则继续迭代,将其中的元素加入到树的广度遍历结果集合中
    		while(list.size() != 0) {
    			// 迭代原始集合中的元素
    			Iterator<T> iterAll = list.iterator();
    			while(iterAll.hasNext()) {
    				T ndInAll = iterAll.next();
    				// 迭代树的广度遍历结果集合中的元素
    				Iterator<T> iterTrav = traversalList.iterator();
    				int indInTrav = 0;// 记录迭代当前元素的位置
    				boolean mate = false;// 标识是否找到父子类匹配关系
    				while(iterTrav.hasNext()) {
    					T ndInTrav = iterTrav.next();
    					// 如果存在父子类关系,则在在树的广度遍历结果集合中添加该元素,并父类中加入子元素
    					if(!mate) {
    						if(ndInAll.isChildFrom(ndInTrav)) {
    							// 如果存在父子类关系,则在父类中加入子元素,并设置标识
    							ndInTrav.addChildNode(ndInAll);
    							mate = true;
    						}
    					} else {
    						// 在找到iterInAll元素的父类之后,继续迭代,找到它的兄弟结点的位置
    						if(ndInAll.isBrother(ndInTrav)) {
    							break;
    						}
    					}
    					indInTrav++; // 执行++之后为迭代当前元素的位置
    				}
    				if(mate) {
    					// 如果找到iterInAll元素的父类,则在它的兄弟结点之前插入该元素
    					traversalList.add(indInTrav, ndInAll);
    					// 移除已经匹配的元素
    					iterAll.remove();
    				}
    			}
    		}
    		// 最后将所有元素已经放到了树的广度遍历结果集合中,并且元素之间建立好了子父关系,即只取根就可得到所有元素
    		T root2 = traversalList.getFirst();
    		return root2;
    	}
    
    	/**
    	 * 通过树的深度优先遍历获取树的遍历集合
    	 * @param root 树的根元素
    	 * @return 深度优先遍历方式的遍历集合
    	 */
    	public static <T extends InheritedNode> List<T> createDepthFirstTraversalList(T root) {
    		List<T> depthFirstTraversalList = new ArrayList<T>();
    		// 深度优先遍历使用的栈结构
    		Deque<T> stack = new ArrayDeque<T>();
    		stack.addFirst(root);
    		T node = null;
    		while((node=stack.pollFirst()) != null) {
    			List<T> sub = node.getChildNodes();
    			if(sub != null && !sub.isEmpty()) {
    				for(int i=0; i<sub.size(); i++) {
    					stack.addFirst(sub.get(i));
    				}
    			}
    			depthFirstTraversalList.add(node);
    		}
    		return depthFirstTraversalList;
    	}
    	
    	/**
    	 * 通过树的广度优先遍历获取树的遍历集合
    	 * @param root 树的根元素
    	 * @return 深度优先遍历方式的遍历集合
    	 */
    	public static <T extends InheritedNode> List<T> createBreadthFirstTraversalList(T root) {
    		List<T> depthFirstTraversalList = new ArrayList<T>();
    		// 广度优先遍历使用的队列结构
    		Deque<T> stack = new ArrayDeque<T>();
    		stack.addLast(root);
    		T node = null;
    		while((node=stack.pollFirst()) != null) {
    			List<T> sub = node.getChildNodes();
    			if(sub != null && !sub.isEmpty()) {
    				for(int i=0; i<sub.size(); i++) {
    					stack.addLast(sub.get(i));
    				}
    			}
    			depthFirstTraversalList.add(node);
    		}
    		return depthFirstTraversalList;
    	}
    	
    	/**
    	 * 打印树形结构,打印部分可以根据业务需求进行修改
    	 * @param root 树的根元素
    	 */
    	public static <T extends InheritedNode> void printTreeByDepthFirstTraversal(T root) {
    		List<T> depthFirstTraversalList = createDepthFirstTraversalList(root);
    		System.out.println(depthFirstTraversalList);
    		// 记录每个元素的深度
    		int[] deepList = new int[depthFirstTraversalList.size()];
    		System.out.printf("%-5s", root);
    		int deep = 1; // 考察的当前元素的深度
    		deepList[0] = 1;
    		for(int i=1; i<depthFirstTraversalList.size(); i++) {
    			if(depthFirstTraversalList.get(i).isChildFrom(depthFirstTraversalList.get(i-1))) {
    				// 如果判断成立,则深度加1
    				deep++;
    				deepList[i] = deep;
    				// 如果上一个元素是当前元素的父亲,则打印
    				System.out.printf("%-5s", depthFirstTraversalList.get(i));
    			} else {
    				// 如果上一个元素不是当前元素的父亲,则回溯迭代找到当前元素的父亲,换行进行打印
    				System.out.println();
    				for(int j=i-2; j>=0; j--) {
    					if(depthFirstTraversalList.get(i).isChildFrom(depthFirstTraversalList.get(j))) {
    						deep = deepList[j] + 1;
    						deepList[i] = deep;
    						// 当前元素之前用空进行打印,在此利用了元素的深度
    						for(int k=0; k<deep-1; k++) {
    							System.out.printf("%-5s", "");
    						}
    						System.out.printf("%-5s", depthFirstTraversalList.get(i));
    						break;
    					}
    				}
    			}
    		}
    		System.out.println();
    	}
    	
    }


    3.结点示例

    1. package subAndsup;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. public class SimpleNode implements InheritedNode<SimpleNode> {  
    7.       
    8.     private String id;  
    9.     private String fid;  
    10.       
    11.     private List<SimpleNode> subSimpleNodeList;  
    12.       
    13.     public SimpleNode(String id, String fid) {  
    14.         this.id = id;  
    15.         this.fid = fid;  
    16.     }  
    17.       
    18.     public void addSubSimpleNode(SimpleNode subSimpleNode) {  
    19.     }  
    20.       
    21.     public String toString() {  
    22.         return id;  
    23.     }  
    24.   
    25.     @Override  
    26.     public void addChildNode(SimpleNode node) {  
    27.         if(subSimpleNodeList == null) {  
    28.             subSimpleNodeList = new ArrayList<SimpleNode>();  
    29.         }  
    30.         subSimpleNodeList.add(node);  
    31.     }  
    32.   
    33.     @Override  
    34.     public List<SimpleNode> getChildNodes() {  
    35.         return subSimpleNodeList;  
    36.     }  
    37.   
    38.     @Override  
    39.     public boolean isBrother(SimpleNode node) {  
    40.         return this.fid.equals(((SimpleNode)node).getFid());  
    41.     }  
    42.   
    43.     @Override  
    44.     public boolean isChildFrom(SimpleNode node) {  
    45.         return this.fid.equals(node.getId());  
    46.     }  
    47.   
    48.     public String getId() {  
    49.         return id;  
    50.     }  
    51.   
    52.     public void setId(String id) {  
    53.         this.id = id;  
    54.     }  
    55.   
    56.     public String getFid() {  
    57.         return fid;  
    58.     }  
    59.   
    60.     public void setFid(String fid) {  
    61.         this.fid = fid;  
    62.     }  
    63.   
    64. }  
    package subAndsup;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class SimpleNode implements InheritedNode<SimpleNode> {
    	
    	private String id;
    	private String fid;
    	
    	private List<SimpleNode> subSimpleNodeList;
    	
    	public SimpleNode(String id, String fid) {
    		this.id = id;
    		this.fid = fid;
    	}
    	
    	public void addSubSimpleNode(SimpleNode subSimpleNode) {
    	}
    	
    	public String toString() {
    		return id;
    	}
    
    	@Override
    	public void addChildNode(SimpleNode node) {
    		if(subSimpleNodeList == null) {
    			subSimpleNodeList = new ArrayList<SimpleNode>();
    		}
    		subSimpleNodeList.add(node);
    	}
    
    	@Override
    	public List<SimpleNode> getChildNodes() {
    		return subSimpleNodeList;
    	}
    
    	@Override
    	public boolean isBrother(SimpleNode node) {
    		return this.fid.equals(((SimpleNode)node).getFid());
    	}
    
    	@Override
    	public boolean isChildFrom(SimpleNode node) {
    		return this.fid.equals(node.getId());
    	}
    
    	public String getId() {
    		return id;
    	}
    
    	public void setId(String id) {
    		this.id = id;
    	}
    
    	public String getFid() {
    		return fid;
    	}
    
    	public void setFid(String fid) {
    		this.fid = fid;
    	}
    
    }


    4.测试:

    1. package subAndsup;  
    2.   
    3. import java.util.LinkedList;  
    4.   
    5. public class Test {  
    6.   
    7.     /** 
    8.      * @param args 
    9.      */  
    10.     public static void main(String[] args) {  
    11.         LinkedList<SimpleNode> list = new LinkedList<SimpleNode>();  
    12.         list.add(new SimpleNode("B2", "B"));  
    13.         list.add(new SimpleNode("D", "A"));  
    14.         list.add(new SimpleNode("C2", "C"));  
    15.         list.add(new SimpleNode("C12", "C1"));  
    16.         list.add(new SimpleNode("D11", "D1"));  
    17.         list.add(new SimpleNode("B1", "B"));  
    18.         list.add(new SimpleNode("B11", "B1"));  
    19.         list.add(new SimpleNode("B12", "B1"));  
    20.         list.add(new SimpleNode("C11", "C1"));  
    21.         list.add(new SimpleNode("B22", "B2"));  
    22.         list.add(new SimpleNode("C1", "C"));  
    23.         list.add(new SimpleNode("B", "A"));  
    24.         list.add(new SimpleNode("D1", "D"));  
    25.         list.add(new SimpleNode("C", "A"));  
    26.           
    27.         SimpleNode root = new SimpleNode("A", null);  
    28.         root = TreeUtil.getTree(root, list);  
    29.           
    30.         TreeUtil.printTreeByDepthFirstTraversal(root);  
    31.           
    32.     }  
    33.   
    34. }  
    package subAndsup;
    
    import java.util.LinkedList;
    
    public class Test {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		LinkedList<SimpleNode> list = new LinkedList<SimpleNode>();
    		list.add(new SimpleNode("B2", "B"));
    		list.add(new SimpleNode("D", "A"));
    		list.add(new SimpleNode("C2", "C"));
    		list.add(new SimpleNode("C12", "C1"));
    		list.add(new SimpleNode("D11", "D1"));
    		list.add(new SimpleNode("B1", "B"));
    		list.add(new SimpleNode("B11", "B1"));
    		list.add(new SimpleNode("B12", "B1"));
    		list.add(new SimpleNode("C11", "C1"));
    		list.add(new SimpleNode("B22", "B2"));
    		list.add(new SimpleNode("C1", "C"));
    		list.add(new SimpleNode("B", "A"));
    		list.add(new SimpleNode("D1", "D"));
    		list.add(new SimpleNode("C", "A"));
    		
    		SimpleNode root = new SimpleNode("A", null);
    		root = TreeUtil.getTree(root, list);
    		
    		TreeUtil.printTreeByDepthFirstTraversal(root);
    		
    	}
    
    }


    5.结果:

    1. [A, C, C1, C11, C12, C2, B, B1, B12, B11, B2, B22, D, D1, D11]  
    2. A    C    C1   C11    
    3.                C12    
    4.           C2     
    5.      B    B1   B12    
    6.                B11    
    7.           B2   B22    
    8.      D    D1   D11    
    [A, C, C1, C11, C12, C2, B, B1, B12, B11, B2, B22, D, D1, D11]
    A    C    C1   C11  
                   C12  
              C2   
         B    B1   B12  
                   B11  
              B2   B22  
         D    D1   D11  
    



  • 相关阅读:
    国内好用的maven仓库,添加到本地nexus中
    02 介绍
    11 jsp脚本调用java代码
    12 jsp page 指令
    14 javaBean 组件
    13 jsp include
    01 Servlet & Jsp 技术概述
    pl/sql 实例精解 05
    pl/sql 实例精解 06
    pl/sql 实例精解 08
  • 原文地址:https://www.cnblogs.com/firstdream/p/5240828.html
Copyright © 2011-2022 走看看