二叉树的常见算法

题记------学习别人的精髓,并加以总结,消化吸收,这就是提高!!!

一、二叉树的创建

部分思路参考自http://ocaicai.iteye.com/blog/1047397

 1 package com.gongli.binary;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import org.junit.Test;
 7 
 8 
 9 /**
10  * 创建二叉树,要注意以下几点
11  * 1、将数组转化为节点,最后一个父节点arr.length/2-1,由右边的子节点是否存在并不确定,需要单独处理
12  * 2、左孩子节点的索引parentIndex*2+1,右孩子节点的索引parentIndex*2+2
13  * @author Administrator
14  */
15 public class CreateBinary {
16     private int[] arr = {1,2,3,4,5,6,7,8,9};
17     private List<Node> nodeList = null;
18     class Node{
19         Node leftChild;
20         Node rightChild;
21         int data;
22         Node(int newData){
23             leftChild = null;
24             rightChild = null;
25             this.data = newData;
26         }
27     }
28     //生成二叉树
29     public List<Node> createBinary(){
30         nodeList = new ArrayList<Node>();
31         //将数组转化为节点
32         for(int i=0;i<arr.length;i++){
33             nodeList.add(new Node(arr[i]));
34         }
35         //对最后一个父节点前的节点按父子节点间的关系建立二叉树
36         for(int parentIndex = 0;parentIndex<arr.length/2-1;parentIndex++){
37             nodeList.get(parentIndex).leftChild = nodeList.get(parentIndex*2+1);
38             nodeList.get(parentIndex).rightChild = nodeList.get(parentIndex*2+2);
39         }
40         int lastIndex = arr.length/2-1;//最后一个父节点
41         //左孩子
42         nodeList.get(lastIndex).leftChild = nodeList.get(lastIndex*2+1);
43         if(arr.length%2==1){//存在右孩子
44             nodeList.get(lastIndex).rightChild = nodeList.get(lastIndex*2+2);
45         }
46         return nodeList;
47     }
48 
49 }

 二、先序、中序、后序三种遍历方式的实现(采用递归和迭代)

  1、先序遍历

 1 /**
 2      * 递归实现先序遍历,即根左右
 3      */
 4     public void beforeTraversal(Node node){
 5         if(node==null){
 6             return;
 7         }
 8         System.out.print(node.data+"  ");
 9         beforeTraversal(node.leftChild);
10         beforeTraversal(node.rightChild);
11     }
12     
13     /**
14      * 迭代实现先序遍历,即根左右,用栈作为辅助容器,顺便复习下栈,切记栈的先进后出原则
     * 该方法思路,结构简单,但不具备扩展性
15 */ 16 public void beforeTraversalStack(Node node){ 17 if(node==null) return;//如果节点为null则直接结束程序 18 Stack<Node> stack = new Stack<Node>(); 19 stack.push(node);//节点入栈 20 //出栈顶元素,与左右孩子入栈,记住右孩子先入栈,才能保证左孩子先出栈 21 while(!stack.isEmpty()){ 22 Node root = stack.pop(); 23 System.out.print(root.data+" "); 24 if(root.rightChild!=null){ 25 stack.push(root.rightChild); 26 } 27 if(root.leftChild!=null){ 28 stack.push(root.leftChild); 29 } 30 } 31 }

  2、中序遍历

 1 /**
 2      * 递归实现中序遍历,即左根右
 3      */
 4     public void middleTraversal(Node node){
 5         if(node==null){
 6             return;
 7         }
 8         middleTraversal(node.leftChild);
 9         System.out.print(node.data+"  ");
10         middleTraversal(node.rightChild);
11     }
12     
13     /**
14      * 迭代实现中序遍历,即左根右,该方法实质是用栈模拟递归过程
15      */
16     public void middleTraversalStack(Node node){
17         if(node==null) return;//如果节点为null则直接结束程序
18         Stack<Node> stack = new Stack<Node>(); 
19         while(node!=null||!stack.isEmpty()){
20             while(node!=null){
21                 stack.push(node);//将根节点入栈
22                 node = node.leftChild;//递归让所有左节点先入栈
23             }
24             node = stack.pop();//左节点入栈完毕后出栈
25             System.out.print(node.data+"  ");
26             node = node.rightChild;//处理右节点
27         }
28     }

  3、后序遍历

 1 /**
 2      * 递归实现后序遍历,即左右根
 3      */
 4     public void afterTraversal(Node node){
 5         if(node==null){
 6             return;
 7         }
 8         afterTraversal(node.leftChild);
 9         afterTraversal(node.rightChild);
10         System.out.print(node.data+"  ");
11     }
12     
13     /**
14      * 迭代实现后序遍历,即左右根,该方法实质是用栈模拟递归过程
15      */
16     public void afterTraversalStack(Node node){
17         if(node==null) return;//如果节点为null则直接结束程序
18         Stack<Node> input = new Stack<Node>();//用于封装node和他的左右孩子 
19         Stack<Node> output = new Stack<Node>();//用于封装栈input翻转后的结果
20         input.push(node);//根节点入栈
21         while(!input.isEmpty()){
22             node = input.pop();//input栈出栈
23             output.push(node);//翻转后入栈
24             if(node.leftChild != null){
25                 input.push(node.leftChild);
26             }
27             if(node.rightChild != null){
28                 input.push(node.rightChild);
29             }
30         }
31         //循环输出output栈中的节点,即为后序遍历
32         while(!output.isEmpty()){
33             System.out.print(output.pop().data+"  ");
34         }
35     }

 三、二叉树节点个数(采用递归和迭代,迭代分别采用栈和队列作为辅助容器)

 1 /**
 2      * 求二叉树节点个数,使用递归,较简单
 3      * 二叉树节点个数=左节点+右节点+根节点
 4      */
 5     public int getNodeNumber(Node node){
 6         if(node == null){
 7             return 0;
 8         }
 9         return getNodeNumber(node.leftChild)+getNodeNumber(node.rightChild)+1;
10     }
11     
12     /**
13      * 求二叉树节点个数,使用迭代
14      * 用队列作为辅助容器
15      */
16     public int getNodeNumberQueue(Node node){
17         if(node==null)return 0;
18         Queue<Node> queue = new LinkedList<Node>();
19         queue.offer(node);
20         int count = 1;//初始化时先把根节点算上
21         while(!queue.isEmpty()){
22             node = queue.poll();//出队
23             if(node.leftChild!=null){
24                 queue.offer(node.leftChild);//左节点入队,重新开始迭代的过程直到全部出队
25                 count++;
26             }
27             if(node.rightChild!=null){
28                 queue.offer(node.rightChild);
29                 count++;
30             }
31         }
32         return count;
33     }
34     
35     /**
36      * 求二叉树节点个数,使用迭代
37      * 用栈作为辅助容器
38      */
39     public int getNodeNumberStack(Node node){
40         if(node==null)return 0;
41         Stack<Node> stack = new Stack<Node>();
42         stack.push(node);
43         int count = 1;//初始化时先把根节点算上
44         while(!stack.isEmpty()){
45             node = stack.pop();//出栈
46             if(node.leftChild!=null){
47                 stack.push(node.leftChild);//左节点入栈,重新开始迭代的过程直到节点全部出栈
48                 count++;
49             }
50             if(node.rightChild!=null){
51                 stack.push(node.rightChild);
52                 count++;
53             }
54         }
55         return count;
56     }

 四、二叉树的深度

 1 /**
 2      * 二叉树的深度,使用递归实现
 3      * 二叉树的深度=max(leftDepth,rightDepth)+1,加1是因为要算上根节点的深度
 4      */
 5     public int getDepth(Node node){
 6         if(node==null){return 0;}
 7         int leftDepth = getDepth(node.leftChild);
 8         int rightDepth = getDepth(node.rightChild);
 9         return Math.max(leftDepth, rightDepth)+1;
10     }

 五、二叉树的分层遍历

    /**
     * 二叉树的分层遍历(从上到下,从左到右),采用迭代实现,递归还没想到
     * 把辅助容器换成栈,则是先序遍历
     */
    public void levelTraversal(Node node){
        if(node==null)return;
        Queue<Node> queue = new LinkedList<Node>();
        queue.offer(node);
        while(!queue.isEmpty()){
            node = queue.poll();
            System.out.print(node.data+"  ");
            if(node.leftChild!=null){
                queue.offer(node.leftChild);
            }
            if(node.rightChild!=null){
                queue.offer(node.rightChild);
            }
        }
    }

六、二叉树第k层节点的个数

 1     /**
 2      * 求二叉树第k层节点的个数,采用递归
 3      */
 4     public int getNodes(Node node,int k){
 5         if(node==null||k<1)return 0;
 6         if(k==1)return 1;
 7         int left = getNodes(node.leftChild,k-1);//左树k-1层的节点数
 8         int right = getNodes(node.rightChild,k-1);//右树k-1层的节点数
 9         return left+right;
10     }

七、判断是否为平衡二叉树

 1 /**
 2      * 判断二叉树是否为平衡二叉树
 3      * 平衡二叉树条件必须满足两点
 4      * 1、左右树的高度差不能超过一
 5      * 2、必须是二叉树
 6      */
 7     public boolean isAVLTree(Node node){
 8         if(node==null)return true;
 9         if(Math.abs(getDepth(node.leftChild)-getDepth(node.rightChild))>1){return false;}//getDeth()为上面写过的树的深度
10         return isAVLTree(node.leftChild)&&isAVLTree(node.rightChild);
11     }
希望各位大神,对文中的不足不吝赐教,共同学习,共同进步!!!
原文地址:https://www.cnblogs.com/gongli123/p/7214742.html