根据父子节点算层级

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

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

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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. }  

2.工具类如下:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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. }  

3.结点示例

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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. }  

4.测试:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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. }  

5.结果:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  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    

猜你喜欢

转载自blog.csdn.net/mezheng/article/details/52954163