• 二叉树的常见算法


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

    一、二叉树的创建

    部分思路参考自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     }
    希望各位大神,对文中的不足不吝赐教,共同学习,共同进步!!!
  • 相关阅读:
    SpringBoot中关于Shiro权限管理的整合使用
    Mybatis批处理(批量查询,更新,插入)
    Windows运行常用命令(win+R)
    IntelliJ IDEA中如何设置同时打开多个文件且分行显示?
    springboot的mybatis的xml相关的配置
    springbootl用thymeleaf整合htm
    resultMap的使用
    重识linux-linux主机上的用户信息传递
    重识linux-linux的新增与删除用户组和切换命令
    重识linux-linux的账号与用户组
  • 原文地址:https://www.cnblogs.com/gongli123/p/7214742.html
Copyright © 2020-2023  润新知