JAVA实现二叉树

      摘要: 一个二叉树的Java实现。可以学习广义表达式及二叉树的递归及非递归处理技巧。

      难度:初级。

 

       为了克服对树结构编程的畏惧感和神秘感,下定决心将二叉树的大部分操作实现一遍,并希望能够掌握二叉树编程的一些常用技术和技巧。

      [1]  数据结构和表示: 二叉树的输入输出格式采用广义表表达式形式,内部表示采用左孩子右孩子的链式存储。

      [2]  已经实现的操作有:

             A. 根据二叉树的广义表表达式来创建二叉树(含表达式合法性检测);

             B. 根据二叉树的前序和中序遍历列表来创建二叉树;

             C. 根据二叉树的中序和后序遍历列表来创建二叉树;

             D. 二叉树的“左孩子右孩子”链式存储转化为广义表表达式;

             E. 二叉树的前序、中序、后序的递归和非递归遍历;层序遍历;结点关联列表;

             F. 求解二叉树的高度、结点总数、叶子结点总数、所有的叶子结点列表;根结点到所有叶子结点的路径;最长路径;

             G. 二叉树复制,二叉树全等性比较,二叉树交换(将二叉树的所有结点的左右子树互换)

       [3]  尚待实现的操作:

             A. 求解二叉树中所有最长(短)路径

             E. 其它

 

       [4]  二叉树 Java 实现代码:

      

  1 /**
  2  * BinaryTree: 实现二叉树,可以根据给定的广义表表达式、前序及中序遍历列表、中序及后序遍历列表创建二叉树;
  3  *             二叉树的前序、中序、后序的递归和非递归遍历,层序遍历;求解二叉树的一些特性
  4  *             
  5  * @author shuqin1984 2011-3-19
  6  * 
  7  */
  8 package datastructure.tree;
  9 import java.util.ArrayList;
 10 import java.util.Iterator;
 11 import java.util.LinkedList;
 12 import java.util.List;
 13 import java.util.regex.Matcher;
 14 import java.util.regex.Pattern;
 15 
 16 public class BinaryTree {
 17     
 18     /**    二叉树的广义表表示  */
 19     private String expression;
 20     /**      树的根结点   */    
 21     private TreeNode  root;
 22     
 23     /** 
 24      * 用于检测二叉树广义表表达式合法性的编译了的正则表达式:
 25      * 合法的广义表表达式可以是:
 26      * [1] 基本表达式: A,A(,), A(B,), A(,B), A(B,C)
 27      * [2] 上述的 A,B,C 可以是 [1] 中的基本表达式
 28      * [3] A,B,C 可允许的取值范围由应用决定,这里仅允许是 大小写字母,数字,+-/*%
 29      * [4] 表达式中不含任何空格符,因此,在检查表达式之前,必须确保表达式中不含空格符
 30      * 
 31      */
 32     private static String permittedChars = "[a-zA-Z0-9//+//-//*/////%]";
 33     private static String basicUnit = "[a-zA-Z0-9//+//-//*/////%//(//),]";
 34     private static Pattern basicPattern = Pattern.compile("" + "|" + permittedChars + "|" + permittedChars + "//(" + permittedChars + "?," + permittedChars + "?//)?");
 35     private static Pattern extendPattern = Pattern.compile(permittedChars + "//(" + basicUnit + "*," + basicUnit + "*//)");
 36     
 37     /**
 38      * 构造器
 39      * @param root 树的根结点
 40      */
 41     public BinaryTree(TreeNode root) {
 42         this.root = root;
 43     }
 44     
 45     /**
 46      * 构造器
 47      * @param expression 二叉树的广义表表达式
 48      */
 49     private BinaryTree(String expression) {
 50         this.expression = expression;
 51     }
 52     /**
 53      * 树结点实现
 54      */
 55     private class TreeNode {
 56         
 57         private char ch;
 58         private TreeNode rchild;
 59         private TreeNode lchild;
 60         
 61         public TreeNode(char ch, TreeNode rchild, TreeNode lchild) {
 62             this.ch = ch;
 63             this.rchild = rchild;
 64             this.lchild = lchild;
 65         }
 66         public char getCh() {
 67             return ch;
 68         }
 69         public TreeNode getRchild() {
 70             return rchild;
 71         }
 72         public void setRchild(TreeNode rchild) {
 73             this.rchild = rchild;
 74         }
 75         public TreeNode getLchild() {
 76             return lchild;
 77         }
 78         public void setLchild(TreeNode lchild) {
 79             this.lchild = lchild;
 80         }    
 81         
 82         public String toString()
 83         {
 84             return "" + getCh();
 85         }
 86     }
 87     
 88     /**
 89      * 结点关联类
 90      */
 91     private class NodeLink {
 92         
 93         private TreeNode node1;
 94         private TreeNode node2;
 95         
 96         public NodeLink(TreeNode node1, TreeNode node2) {
 97             this.node1 = node1;
 98             this.node2 = node2;
 99         }
100         
101         public String toString() {
102             
103             return "(" + node1.getCh() + "," + node2.getCh() + ")";
104         }
105             
106     }
107     
108     /**
109      *  【设置/获取】属性
110      */
111     public TreeNode getRoot() {
112         return root;
113     }
114     public void setRoot(TreeNode root) {
115         this.root = root;
116     }
117     
118     
119     /**
120      * getPreOrderList: 获得树的先序遍历列表
121      * @param flag 是否采用递归遍历的标记;若 flag = true, 采用递归遍历;否则,采用非递归遍历
122      * @return 二叉树的先序遍历列表
123      */
124     
125     public List<TreeNode> getPreOrderList(boolean flag) {
126         
127         List<TreeNode>    nodelist = new ArrayList<TreeNode>();
128         if (flag == true) {
129            nodelist = preOrderTraverse(getRoot(), nodelist);
130         }
131         else {
132            nodelist = preOrderTraverseIter(getRoot());
133         }
134         return nodelist;
135     }
136     
137     /**
138      * getInOrderList: 获得树的中序遍历列表
139      * @param flag 是否采用递归遍历的标记;若 flag = true, 采用递归遍历;否则,采用非递归遍历
140      * @return 获得树的中序遍历列表
141      */
142     
143     public List<TreeNode> getInOrderList(boolean flag) {
144         
145         List<TreeNode>    nodelist = new ArrayList<TreeNode>();
146         if (flag == true) {
147            nodelist = inOrderTraverse(getRoot(), nodelist);
148         }
149         else {
150            nodelist = inOrderTraverseIter(getRoot());
151         }
152         return nodelist;
153     }
154     
155     /**
156      * getPostOrderList: 获得树的后序遍历列表
157      * @param flag 是否采用递归遍历的标记;若 flag = true, 采用递归遍历;否则,采用非递归遍历
158      * @return 获得树的后序遍历列表
159      */
160     
161     public List<TreeNode> getPostOrderList(boolean flag) {
162         
163         List<TreeNode>    nodelist = new ArrayList<TreeNode>();
164         if (flag == true) {
165             nodelist = postOrderTraverse(getRoot(), nodelist);
166         }
167         else {
168             nodelist = postOrderTraverseIter(getRoot());
169         }
170         return nodelist;
171     }
172     
173     /**
174      * 获得树的层序遍历列表
175      * 
176      * @return 获得树的层序遍历列表
177      */
178     
179     public List<TreeNode> getFloorOrderList() {
180         
181         List<TreeNode>    nodelist = new ArrayList<TreeNode>();
182         nodelist = floorOrderTraverse(getRoot());
183         return nodelist;
184     }
185     
186     /**
187      * createBinaryTree: 根据树的广义表表示构造二叉树
188      * @throws Exception 
189      */
190     public static BinaryTree createBinaryTree(String expression) throws Exception 
191     {
192         BinaryTree bt = new BinaryTree(trimSpace(expression));
193         bt.createBinaryTree();
194         return bt;
195     }
196     
197     /**
198      * createBinaryTree: 根据二叉树的广义表表达式来创建二叉树
199      * @exception 若二叉树的广义表表达式不合法,则抛出异常
200      */
201     private void createBinaryTree() throws Exception {
202         
203         // 检查传入的二叉树广义表示法是否合法有效
204         if (!checkValid(expression))
205             throw new Exception("广义表表达式不合法,无法创建二叉树!");
206         
207         // 使用 LinkedList 来执行栈的功能
208         LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
209         TreeNode newnode = null;
210         int flag = 0;  //  flag = 0: 创建左子树 | flag = 1: 创建右子树
211         
212         for (char ch: expression.toCharArray()) {
213             switch (ch) {
214                
215                // 遇到  "(" 时,表示该结点可能有孩子结点,将该父结点压入栈中
216                case '(': 
217                    stack.push(newnode);
218                    flag = 0;
219                    break;
220                    
221                // 遇到  ")" 时,表示已经扫描完父结点的右孩子结点的值,弹出该父结点       
222                case ')':
223                    stack.pop();
224                    break;
225                    
226               // 遇到 "," 时, 表示将要扫描父结点的右孩子结点的值。       
227                case ',':
228                    flag = 1;
229                    break;       
230               
231               // 遇到结点的值,将其加入二叉树中       
232                default:
233                    
234                     newnode = new TreeNode(ch, null, null);
235                     if (root == null) {
236                            root = newnode;
237                     }
238                     else {
239                            if (flag == 0) {
240                               TreeNode topnode = stack.peek();
241                               topnode.setLchild(newnode);
242                            }
243                            else 
244                            {
245                                TreeNode topnode = stack.peek();
246                                topnode.setRchild(newnode); 
247                            }
248                     }
249                     break;           
250             }
251         }        
252     }
253     
254     /**
255      * checkValid: 判断给定二叉树的广义表表示是否合法有效
256      *             
257      * @param expression 给定二叉树的广义表表示【字符串形式】
258      * @return 如果给定的二叉树广义表表示合法有效,返回true; 否则,返回 false
259      * 
260      */
261     private static boolean checkValid(String expression)
262     {
263         Matcher m = null;
264         if (basicPattern.matcher(expression).matches())
265             return true;
266         else if ((m = extendPattern.matcher(expression)).matches()) {
267             int index = separatorIndex(expression);
268             if (index == -1) {  // 不存在能够分割二叉树广义表达式的左右子树表达式的逗号
269                 return false;
270             }
271             String rightEx = "";
272             String leftEx = ""; 
273             if (index > 2) {
274                 leftEx = expression.substring(2, index);  // 左子树的广义表达式
275             }
276             if (index < expression.length()-2) { 
277                   rightEx = expression.substring(index+1, expression.length()-1);  // 右子树的广义表达式
278             }
279             return checkValid(leftEx) && checkValid(rightEx);        
280         }
281         else {
282             return false;
283         }
284     }
285     
286     
287     /**
288      * getGeneralList: 获取该二叉树的广义表表示(字符串表示)
289      */
290     public String getGeneralListString()
291     {
292         StringBuilder sb = new StringBuilder("");
293         if (expression == null) {
294             createGeneralList(root, sb);
295             return sb.toString();
296         }
297         return  expression;        
298     }
299     
300     /**
301      * getGeneralList: 根据给定二叉树生成其广义表表示(字符串形式)
302      * @param root 树的根结点
303      * @return 树的广义表表示【字符串形式】
304      */    
305     private void createGeneralList(TreeNode root, StringBuilder sb) {
306         
307         if (root != null) {
308             
309             sb.append(root.getCh());
310             if (root.getLchild() != null || root.getRchild() != null) {
311                 sb.append('(');
312                 if (root.getLchild() != null) {
313                     createGeneralList(root.getLchild(), sb);
314                 }
315                 sb.append(',');
316                 if (root.getRchild() != null) {                
317                     createGeneralList(root.getRchild(), sb);        
318                 }
319                 sb.append(')');
320             }    
321         }            
322     }
323     
324     /**
325      * size: 获取二叉树的结点总数
326      *  
327      * @param root 树的根结点
328      * @return  树的结点总数
329      * 
330      */
331     public int size(TreeNode root) {
332         
333         if (root == null)
334             return 0;
335         else {
336             return size(root.getLchild()) + size(root.getRchild()) + 1;
337         }
338     }
339     
340     /**
341      * leafCounter: 获取二叉树的叶子结点数目
342      * 
343      * @param root 树的根结点
344      * @return  树的叶子结点数目
345      * 
346      */
347     public int leafCounter(TreeNode root) {
348         if (root == null)
349             return 0;
350         else {
351             if (root.getLchild() == null && root.getRchild() == null)
352                 return 1;
353             else
354                 return leafCounter(root.getLchild()) + leafCounter(root.getRchild());
355         }
356     }
357     
358     /**
359      * getLeafNodes : 获取该二叉树的所有叶子结点
360      */
361     public List<TreeNode> getLeafNodes()
362     {
363         List<TreeNode> leaflist = new ArrayList<TreeNode>();
364         getLeafNodes(getRoot(), leaflist);
365         return leaflist;
366     }
367     
368     /**
369      * printLeafPaths : 打印该二叉树的所有叶子结点到根的路径
370      */
371     public void printLeafPaths()
372     {
373         List<TreeNode> leafPath = new ArrayList<TreeNode>();
374         buildLeafPaths(root, leafPath);
375     }
376     
377     /**
378      * buildLeafPaths : 递归求解给定二叉树的所有叶子结点到根的路径
379      * @param root 给定二叉树的根结点
380      * @param path 存放某个叶子结点到根的路径
381      */
382     public void buildLeafPaths(TreeNode root, List<TreeNode> path)
383     {
384         if (root != null) {    
385             path.add(root);  // 将从根结点到叶子结点的路径上的结点保存起来
386             if (root.getLchild() == null && root.getRchild() == null) { // 到达叶子结点,完成一条路径,并可对其处理
387                 processPath(path);
388             }
389             else {
390                 buildLeafPaths(root.getLchild(), path);
391                 if (root.getLchild() != null) {      
392                    path.remove(path.size()-1);  // 回溯,从左子树到右子树,删除前一条路径上的叶子结点
393                 }
394                 buildLeafPaths(root.getRchild(), path);
395                 if (root.getRchild() != null) {
396                    path.remove(path.size()-1);
397                 }
398             }
399         }
400     }
401     
402     /**
403      * processPath : 处理从某叶子结点到根结点的路径的操作
404      */
405     private void processPath(List<TreeNode> path)
406     {
407         System.out.println(listToString(path));
408     }
409     
410     /**
411      * getLeafNodes: 递归求解给定二叉树的所有叶子结点
412      * @param root   给定二叉树的根结点
413      * @param leaflist 给定二叉树的所有叶子结点
414      */
415     private void getLeafNodes(TreeNode root, List<TreeNode> leaflist)
416     {
417         if (root != null) {
418             if (root.getLchild() == null && root.getRchild() == null) {
419                 leaflist.add(root);
420                 return ;
421             }
422             getLeafNodes(root.getLchild(), leaflist);
423             getLeafNodes(root.getRchild(), leaflist);
424         }
425     }
426     
427     
428     /**
429      * height: 获取二叉树的高度 
430      * 
431      * @param root   树的根结点
432      * @return       树的高度
433      *  
434      */
435     
436     public int height(TreeNode root)
437     {
438         if (root == null)
439             return 0;
440         else
441             return 1 + Math.max(height(root.getLchild()), height(root.getRchild()));
442     }
443     
444     /**
445      * getNodelinkList: 获取该二叉树的结点关联列表
446      * @return 树的结点关联列表
447      */
448     public List<NodeLink> getNodelinkList() {
449         
450         List<NodeLink> linklist = new ArrayList<NodeLink>();
451         createNodelinkList(getRoot(), linklist);
452         return linklist;
453         
454     }
455         
456     /**
457      * createNodelinkList: 递归求解给定二叉树的结点关联列表表示
458      * @param root 给定二叉树的根结点
459      * @param linklist 存放给定二叉树的结点关联对象
460      */
461     private void createNodelinkList(TreeNode root, List<NodeLink> linklist) {
462         
463         if (root != null) {
464             if (root.getLchild() != null) {
465                 NodeLink nodelink = new NodeLink(root, root.getLchild());
466                 linklist.add(nodelink);
467                 createNodelinkList(root.getLchild(), linklist);
468             }
469             if (root.getRchild() != null) {
470                 NodeLink nodelink = new NodeLink(root, root.getRchild());
471                 linklist.add(nodelink);
472                 createNodelinkList(root.getRchild(), linklist);
473             }
474         }
475     }
476     
477     /**
478      * preOrderTraverse: 二叉树的递归先序遍历
479      * 
480      */
481     private List<TreeNode> preOrderTraverse(TreeNode root, List<TreeNode> nodelist) {
482         
483         if (root != null) {
484             nodelist.add(root);
485             preOrderTraverse(root.getLchild(), nodelist);    
486             preOrderTraverse(root.getRchild(), nodelist);
487         }
488         
489         return nodelist;
490     }
491     
492     /**
493      * preOrderTraverseIter: 二叉树的非递归先序遍历
494      */
495     private List<TreeNode> preOrderTraverseIter(TreeNode root) {
496         LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
497         List<TreeNode> nodelist = new ArrayList<TreeNode>();
498         TreeNode pNode = root;
499         for (;;) {
500             while (pNode != null) {
501                 nodelist.add(pNode);        // 访问根结点
502                 stack.push(pNode);          // 根结点入栈    
503                 pNode = pNode.getLchild();  // 访问左子树
504             }    
505             pNode = stack.pop();
506             pNode = pNode.getRchild();      // 访问右子树
507             if (pNode == null && stack.isEmpty()) { break; }
508         }           
509         return nodelist;
510     }
511     
512     /**
513      * inOrderTraverse: 二叉树的递归中序遍历
514      * 
515      */
516     private List<TreeNode> inOrderTraverse(TreeNode root, List<TreeNode> nodelist) {
517         
518         if (root != null) {
519             inOrderTraverse(root.getLchild(), nodelist);
520             nodelist.add(root);
521             inOrderTraverse(root.getRchild(), nodelist);
522         }
523         
524         return nodelist;
525     }
526     
527     /**
528      * inOrderTraverseIter: 二叉树的非递归中序遍历
529      */
530     
531     private List<TreeNode> inOrderTraverseIter(TreeNode root) {
532         
533         LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
534         List<TreeNode> nodelist = new ArrayList<TreeNode>();
535         
536         TreeNode pNode = root;
537         for (;;) {
538             while (pNode != null) {            // 访问左子树
539                 stack.push(pNode);      
540                 pNode = pNode.getLchild();
541             }
542             pNode = stack.pop();   
543             nodelist.add(pNode);               // 访问根结点
544             pNode = pNode.getRchild();           // 访问右子树
545             if (pNode == null && stack.isEmpty()) { break; }
546         }
547         
548         return nodelist;
549     }
550     
551     /**
552      * postOrderTraverse: 二叉树的递归后序遍历
553      */
554     private List<TreeNode> postOrderTraverse(TreeNode root, List<TreeNode> nodelist) {
555         
556         if (root != null) {
557             postOrderTraverse(root.getLchild(), nodelist);
558             postOrderTraverse(root.getRchild(), nodelist);
559             nodelist.add(root);
560         }
561         
562         return nodelist;
563     }
564     
565     /**
566      * postOrderTraverseIter: 二叉树的非递归后序遍历
567      */
568     private List<TreeNode> postOrderTraverseIter(TreeNode root) {
569         
570         LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
571         List<TreeNode> nodelist = new ArrayList<TreeNode>();
572         
573         int flag = 0;  // 标识是否访问过右子树; flag = 0 表示没有访问; flag = 1 表示已经访问过
574         TreeNode pNode = root;
575         TreeNode tmpNode = null;
576         loop1:
577         for (;;) {
578             while (pNode != null) {        // 访问左子树
579                 stack.push(pNode);     
580                 pNode = pNode.getLchild();
581                 flag = 0;
582             }
583             loop2:
584             for (;;) {
585                 if (!stack.isEmpty()) {
586                     
587                     if (flag == 0)               // 尚未访问根结点的右子树
588                     {
589                        pNode = stack.peek();     // 取根结点的右子树,访问其右子树
590                        pNode = pNode.getRchild(); 
591                        flag = 1;
592                        continue loop1;
593                     }
594                     
595                     if (flag == 1) {            // 已经访问过右子树
596                         pNode = stack.pop();
597                         nodelist.add(pNode);    // 访问根结点,实际上是左右子树均为空的叶子结点 
598                         tmpNode = pNode;        // 访问某个结点后,立即访问其父结点的右子树
599                         pNode = stack.peek();   // 取该结点的父结点    
600                         if (pNode != null) {    // 父结点不为空(没有回溯到整棵树的根结点)
601                             if (tmpNode == pNode.getRchild()) { 
602                                 // 如果刚刚访问的结点正是其父结点的右孩子,则直接回溯访问其父结点; 
603                                 continue loop2; 
604                             }
605                             else {  // 否则,访问其父结点的右子树
606                                 pNode = pNode.getRchild();
607                                 continue loop1;
608                             }
609                         } 
610                         
611                     }
612                     
613                     
614                 }
615                 else   // 栈空,递归调用结束,退出
616                 {
617                     break loop1;
618                 }
619             }    
620             
621         }
622         return nodelist;
623     }
624     
625     /**
626      * floorOrderTraverse: 二叉树的层序遍历
627      * 
628      * @param  root 树的根结点
629      * @return 树的层序遍历列表
630      * 
631      */
632     private List<TreeNode> floorOrderTraverse(TreeNode root) {
633         
634         // 使用 LinkedList 来执行队列的功能
635         LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
636         List<TreeNode> nodelist = new ArrayList<TreeNode>();
637         if (root != null) {
638             nodelist.add(root);
639             queue.addLast(root);
640             while(queue.size() > 0) {
641                 TreeNode node = queue.removeFirst();
642                 if (node.getLchild() != null) {
643                     nodelist.add(node.getLchild());
644                     queue.addLast(node.getLchild());
645                 }   
646                 if (node.getRchild() != null) {
647                     nodelist.add(node.getRchild());
648                     queue.addLast(node.getRchild());
649                 }    
650             }
651         }
652         
653         return nodelist;
654     }
655     
656     /**
657      * copyBinaryTree: 复制二叉树
658      * @return 复制后的二叉树
659      */
660     public BinaryTree copyBinaryTree()
661     {
662         TreeNode anotherRoot = null;
663         anotherRoot = copy(getRoot());
664         return new BinaryTree(anotherRoot);
665     }
666     
667     /**
668      * copy: 复制二叉树
669      * @param srcRoot 要复制的二叉树的根结点
670      * @param destRoot 目标二叉树的根结点
671      */
672     private TreeNode copy(TreeNode srcRoot)
673     {
674         if (srcRoot != null) {
675             TreeNode newNode = new TreeNode(srcRoot.getCh(), null, null);
676             newNode.setLchild(copy(srcRoot.getLchild()));
677             newNode.setRchild(copy(srcRoot.getRchild()));
678             return newNode;
679         }
680         return null;
681     }
682     
683     /**
684      * equalsTo: 比较该二叉树与给定二叉树 another 是否全等;
685      *           若全等则返回 true, 否则返回 false.
686      */
687     public boolean equalsTo(BinaryTree another)
688     {
689         return compareEqual(root, another.getRoot());
690     }
691     
692     /**
693      * equalsTo : 比较给定的两个二叉树是否全等
694      *            两个二叉树全等当且仅当 
695      *            A. 两个二叉树均为空; 或者 
696      *            B. 两个二叉树均非空,且所有对应位置的结点都相同,对应结点之间的关联也完全相同.
697      */
698     private boolean compareEqual(TreeNode root, TreeNode anotherRoot)
699     {
700         return (root == null && anotherRoot == null) || 
701                ((root != null && anotherRoot != null) &&
702                 (root.getCh() == anotherRoot.getCh()) &&
703                 (compareEqual(root.getLchild(), anotherRoot.getLchild())) && 
704                 (compareEqual(root.getRchild(), anotherRoot.getRchild())));
705     }
706     
707     /**
708      * swapTree : 将该二叉树的所有结点的左右孩子互换
709      */
710     public void swapTree()
711     {
712         StringBuilder sb = new StringBuilder("");
713         swapTree(root);
714         createGeneralList(root, sb);
715         expression = sb.toString();
716     }
717     
718     /**
719      * swapTree : 将给定的二叉树的所有结点的左右孩子互换
720      * @param root 给定二叉树的根结点
721      */
722     private void swapTree(TreeNode root)
723     {
724         if (root != null) {
725             TreeNode tmp = root.getLchild();
726             root.setLchild(root.getRchild());
727             root.setRchild(tmp);
728             swapTree(root.getLchild());
729             swapTree(root.getRchild());
730         }
731     }
732      
733     /**
734      * longestPath: 获取该二叉树中的一条最长路径
735      * @return 二叉树中的一条最长路径
736      */
737     public List<TreeNode> longestPath() 
738     {
739         List<TreeNode> longestPath = new ArrayList<TreeNode>();
740         longestPath(root, longestPath);
741         return longestPath;
742     }
743     
744     /**
745      * longestPath: 递归求解给定二叉树的一条最长路径
746      * @param root  给定二叉树的根结点
747      * @param longestPath 存放二叉树的最长路径上的结点
748      */
749     private void longestPath(TreeNode root, List<TreeNode> longestPath)
750     {
751         if (root != null) {
752             longestPath.add(root);
753             if (root.getLchild() == null && root.getRchild() == null) { // 左右子树均空
754                  return ;
755             }
756             if (root.getLchild() != null && root.getRchild() == null) { // 左子树非空,右子树为空,则最长路径的结点必在左子树路径上
757                 longestPath(root.getLchild(), longestPath);
758             }
759             if (root.getLchild() == null && root.getRchild() != null) { // 左子树非空,右子树为空,则最长路径的结点必在右子树路径上
760                 longestPath(root.getRchild(), longestPath);
761             }
762             if (root.getLchild() != null && root.getRchild() != null) { // 左右子树均非空;分别求解左右子树的最长路径,取最大者
763                 List<TreeNode> leftLongestPath = new ArrayList<TreeNode>();
764                 List<TreeNode> rightLongestPath = new ArrayList<TreeNode>();
765                 longestPath(root.getLchild(), leftLongestPath);
766                 longestPath(root.getRchild(), rightLongestPath);
767                 if (leftLongestPath.size() >= rightLongestPath.size()) {
768                     longestPath.addAll(leftLongestPath);
769                 } else if (leftLongestPath.size() < rightLongestPath.size()) {
770                     longestPath.addAll(rightLongestPath);
771                 }
772                 
773             }
774         }
775     }
776     
777     
778     
779     /**
780      * listToString: 返回二叉树的结点列表的字符串表示
781      * 
782      * @param nodelist  树的结点列表
783      * @return  二叉树的结点列表的字符串表示 
784      * 
785      */
786     public String listToString(List<TreeNode> nodelist) {
787         
788         if (nodelist == null || nodelist.size() == 0) {
789             return "[ 空树 ]";
790         }
791         StringBuilder str = new StringBuilder("[");
792         Iterator<TreeNode> iter = nodelist.iterator();
793         while (iter.hasNext()) {
794             TreeNode node = iter.next();
795             str.append(node.getCh()+" ");
796         }
797         str.deleteCharAt(str.length()-1);
798         str.append(']');
799         return str.toString();
800     }
801     
802     
803     /**
804      * createBinaryTree: 根据前序和中序遍历列表生成二叉树
805      * 
806      * @param preOrderList  前序列表字符串
807      * @param inOrderList   中序列表字符串
808      * @throws Exception 
809      * 
810      */
811     public static BinaryTree createBinaryTree(String preOrderList, String inOrderList) throws Exception {
812         BinaryTree bt = new BinaryTree(getGeneralList(preOrderList, inOrderList));
813         bt.createBinaryTree();
814         return bt;
815     }
816     
817     /**
818      * getGeneralist: 根据前序和中序遍历列表生成二叉树的广义表表示【字符串形式】
819      * 
820      * @param preOrderList  前序列表字符串
821      * @param inOrderList   中序列表字符串
822      * @return generalList  广义表表示
823      * 
824      */
825     
826     private static String getGeneralList(String preOrderList, String inOrderList) {
827         
828         String s = "";
829         if (preOrderList.length() > 0 || inOrderList.length() > 0) {
830             
831             // 如果只含一个结点值,就直接返回
832             if (preOrderList.length() == 1)
833                 return preOrderList;
834             
835             // 根据前序遍历, 第一个是根结点的值
836             char ch = preOrderList.charAt(0); 
837             
838             // 根据中序遍历及根结点,将前序列表分为左右子树列表。
839             int index = inOrderList.indexOf(ch);
840             String inOrderLeft = inOrderList.substring(0, index);                     // 左子树的中序遍历列表
841             String inOrderRight = inOrderList.substring(index+1);                     // 右子树的中序遍历列表
842             String preOrderLeft = preOrderList.substring(1, inOrderLeft.length()+1);  // 左子树的前序遍历列表
843             String preOrderRight = preOrderList.substring(inOrderLeft.length()+1);    // 右子树的前序遍历列表
844             s += ch;
845             s += "(" + getGeneralList(preOrderLeft,inOrderLeft) + "," + getGeneralList(preOrderRight,inOrderRight) + ")"; 
846         }
847         return s;
848     }
849     
850     /**
851      * createBinaryTree: 根据中序和后序遍历列表生成二叉树
852      * 
853      * @param  inOrderList   中序列表
854      * @param  postOrderList 后序列表
855      * @param  flag          标记
856      * 
857      * @throws Exception 
858      */
859     public static BinaryTree createBinaryTree(String inOrderList, String postOrderList, boolean flag) throws Exception {
860         BinaryTree bt = new BinaryTree(getGeneralList(inOrderList, postOrderList, flag));
861         bt.createBinaryTree();
862         return bt;
863     }
864     
865     
866     
867     /**
868      * getGeneralList: 根据中序和后序遍历生成二叉树的广义表表示【字符串形式】
869      * 
870      * @param  inOrderList   中序列表
871      * @param  postOrderList 后序列表
872      * @param  flag          标记
873      * @return generalList   广义表表示
874      * 
875      */
876     
877     private static String getGeneralList(String inOrderList, String postOrderList, boolean flag) {
878         
879         String s = "";
880         if (inOrderList.length() > 0 || postOrderList.length() >0) {
881             
882             // 如果只含一个结点值,就直接返回
883             if (inOrderList.length() == 1) 
884                 return inOrderList;
885             
886             // 根据后序遍历规则,最后一个是根结点的值
887             char ch = postOrderList.charAt(postOrderList.length()-1); 
888             
889             // 根据中序遍历及根结点,将前序列表分为左右子树列表。
890             int index = inOrderList.indexOf(ch);
891             String inOrderLeft = inOrderList.substring(0, index);                     // 左子树的中序遍历列表
892             String inOrderRight = inOrderList.substring(index+1);                     // 右子树的中序遍历列表
893             String postOrderLeft = postOrderList.substring(0, inOrderLeft.length());  // 左子树的前序遍历列表
894             String postOrderRight = postOrderList.substring(inOrderLeft.length(), 
895                                     inOrderLeft.length()+inOrderRight.length());    // 右子树的前序遍历列表
896             s += ch;
897             s += "(" + getGeneralList(inOrderLeft,postOrderLeft,true) + "," + getGeneralList(inOrderRight,postOrderRight,true) + ")"; 
898         }
899         return s;
900     }
901     
902     /**
903      * trimSpace: 将广义表表达式字符串中的空格符去掉
904      */
905     private static String trimSpace(String s)
906     {
907         StringBuilder sb = new StringBuilder("");
908         for (int i=0; i < s.length(); i++) {
909             char ch = s.charAt(i);
910             if (!(new Character(ch).toString().matches("//s"))) {   
911                 sb.append(ch);
912             }
913         }
914         return sb.toString();
915     }
916     
917     /**
918      * separatorIndex : 求解广义表表达式中分割左右子树的分隔符的位置
919      *                  由于这里使用逗号分割左右子树,则当且仅当其位置应当满足:
920      *                  在该分割符之前,左括号的数目恰好比右括号的数目多1. 
921      * @return  若存在满足条件的分隔符,则返回其位置;否则返回 -1
922      */
923     private static int separatorIndex(String expression)
924     {
925         int leftBracketCounter=0, rightBacketCounter=0;
926         int index = 0;
927         for (; index < expression.length(); index++) {
928             char ch = expression.charAt(index);
929             if (ch == '(') {
930                 leftBracketCounter++;
931             }
932             else if (ch == ')') {
933                 rightBacketCounter++;
934             }
935             else if (ch == ',') {
936                 if (leftBracketCounter == rightBacketCounter+1) break;
937             }
938         }
939         if (index < expression.length()) {
940             return index;
941         }
942         return -1;
943     }
944     
945 }

 

  

posted @ 2014-10-20 18:55  琴水玉  阅读(2923)  评论(2编辑  收藏  举报