• 数据结构与算法之二叉树


      关于二叉树,首先搞清楚“树”,这里面有几个重要的概念:高度(Height)、深度(Depth)、层(Level)。

    节点的高度 = 节点到叶子节点的最长路径(边数)

    节点的深度 = 根节点到这个节点所经历的边的个数

    节点的层数 = 节点的深度 + 1

    树的高度 = 根节点的高度

    (这张图可以帮助理解一下)

    对于二叉树,首先要搞清楚二叉树的概念以及一些特点,这样才能更好的使用二叉树这种数据结构

     二叉树:每个节点最多有两个叉,也就是最多有两个子节点,分别是左子节点和右子节点,不过,二叉树并不要求每个节点都有两个子节点,有的节点只有左子节点,有的节点只有右子节点。

    满二叉树:叶子节点全部都在最底层,除了叶子节点之外,每个节点都有左右两个子节点

    完全二叉树:叶子节点都在最底下两层,最后一层的叶子节点都靠左排列,并且除了最后一层,其他层的节点个数都要达到最大

    一、二叉树的遍历

    前序遍历:对于树中的任意节点,先打印这个节点本身,再打印它的左子树,最后打印它的右子树

    中序遍历:对于树中的任意节点,先打印它的左子树,再打印这个节点本身,最后打印它的右子树

    后序遍历:对于树中的任意节点,先打印它的左子树,再打印它的右子树,最后打印这个节点本身

    /**
     * 二叉树(Binary Tree)节点类
     * @author ssc
     * @date 2018.11.16
     */
    public class BinaryTreeNode {
    
        int data;
        BinaryTreeNode left;
        BinaryTreeNode right;
        
        public BinaryTreeNode(int data){
            this.data = data;
        }
    }
    
    /**
         * 先序遍历
         * 先打印该节点  再打印左子树  然后再打印右子树
         * 这三种不同的遍历结构都是一样的,仅仅是先后顺序不一样而已
         * 
         * @param node 遍历的节点
         */
        public  void preOrderTraverse(BinaryTreeNode node) {
            if (node == null){
                return;
            }
            System.out.print(node.data + " ");
            preOrderTraverse(node.left);
            preOrderTraverse(node.right);
        }
    
        /**
         * 中序遍历
         * 
         * 这三种不同的遍历结构都是一样的,仅仅是先后顺序不一样而已
         * 先打印左子树  再打印此节点本身  最后打印右子树
         * @param node 遍历的节点
         */
        public  void inOrderTraverse(BinaryTreeNode node) {
            if (node == null){
                return;
            }
            inOrderTraverse(node.left);
            System.out.print(node.data + " ");
            inOrderTraverse(node.right);
        }
    
        /**
         * 后序遍历
         * 
         * 这三种不同的遍历结构都是一样的。仅仅是先后顺序不一样而已
         * 先打印左子树  然后再打印右子树 最后打印此节点本身
         * @param node 遍历的节点
         */
        public  void postOrderTraverse(BinaryTreeNode node) {
            if (node == null){
                return;
            }
            postOrderTraverse(node.left);
            postOrderTraverse(node.right);
            System.out.print(node.data + " ");
        }

     二、二叉查找树

    二叉查找树:二叉查找树是为了实现快速查找而生的。不过,它不仅仅支持快速查找一个数据,还支持快速插入、删除一个数据

    满足二叉查找树的要求:在树中的任意一个节点,其左子树中每个节点的值,都要小于这个节点的值,右子树节点的值大于这个节点的值

      1 /**
      2  * 二叉树(Binary Tree)节点类
      3  * @author ssc
      4  * @date 2018.11.16
      5  */
      6 public class BinaryTreeNode {
      7 
      8     int data;
      9     BinaryTreeNode left;
     10     BinaryTreeNode right;
     11     
     12     public BinaryTreeNode(int data){
     13         this.data = data;
     14     }
     15     
     16 }
     17 
     18 /**
     19  * 二叉查找树(Binary Search Tree)
     20  * 
     21  * 二叉查找树满足的条件:(在树中的任意一个节点,左子树中的每个节点的值都要小于这个节点的值,右子树中每个节点的值都要大于这个节点的值)
     22  * @author ssc
     23  * @date 2018.11.16
     24  */
     25 public class BinarySearchTree {
     26 
     27     private BinaryTreeNode tree;
     28     
     29     /**
     30      * 二叉树中的查找操作
     31      * @param data 需要查找的数值
     32      * @return
     33      * 
     34      */
     35     public BinaryTreeNode find(int data){
     36         BinaryTreeNode p = tree;
     37         
     38         while(p != null){
     39             if(data < p.data){
     40                 //查找的数据比根节点小 就在左子树中递归查找
     41                 p = p.left;
     42             }else if(data > p.data){
     43                 //查找的数据比根节点大 就在右子树中递归查找
     44                 p = p.right;
     45             }else{
     46                 return p;
     47             }
     48         }
     49         return null;
     50     }
     51     
     52     /**
     53      * 二叉查找树的插入操作
     54      * @param data
     55      */
     56     public void insert(int data){
     57         if(tree == null){
     58             tree = new BinaryTreeNode(data);
     59             return;
     60         }
     61         
     62         BinaryTreeNode p = tree;
     63         while(p != null){
     64             if(data > p.data){
     65                 //插入到右子树
     66                 if(p.right == null){
     67                     p.right = new BinaryTreeNode(data);
     68                     return;
     69                 }
     70                 p = p.right;
     71             }else{
     72                 //data < p.data
     73                 //插入到左子树
     74                 if(p.left == null){
     75                     p.left = new BinaryTreeNode(data);
     76                     return;
     77                 }
     78                 p = p.left;
     79             }
     80         }
     81     }
     82     
     83     /**
     84      * 二叉查找树 中的删除操作
     85      * @param data
     86      */
     87     public void delete(int data){
     88         //p指向要删除的节点  初始化指向根节点
     89         BinaryTreeNode p = tree;
     90         //pp记录的是p的父节点
     91         BinaryTreeNode pp = null;
     92         
     93         while(p != null && p.data != data){
     94             pp = p;
     95             if(data > p.data){
     96                 p = p.right;
     97             }else{
     98                 p = p.left;
     99             }
    100         }
    101         
    102         //没有找到
    103         if(p == null){
    104             return ;
    105         }
    106         
    107         //要删除的节点有两个子节点
    108         if(p.right != null && p.left != null){
    109             //查找右子树中的最小节点
    110             BinaryTreeNode minP = p.right;
    111             //minPP是minP的父节点
    112             BinaryTreeNode minPP = p;
    113             while(minP.left != null){
    114                 minPP = minP;
    115                 minP = p.left;
    116             }
    117             //将minP 的数据替换到p 中
    118             p.data = minP.data;
    119             //删除minP
    120             p = minP;
    121             pp = minPP;
    122         }
    123         
    124         //删除节点是叶子节点 或仅有一个子节点
    125         //p 的子节点
    126         BinaryTreeNode child;
    127         if(p.left != null){
    128             child = p.left;
    129         }else if(p.right != null){
    130             child = p.right;
    131         }else{
    132             child = null;
    133         }
    134         
    135         if(pp == null){
    136             tree = child;
    137         }else if(pp.left == p){
    138             pp.left = child;
    139         }else{
    140             pp.right = child;
    141         }
    142     }
    143 }

    此大部分内容来自极客时间专栏,王争老师的《数据结构与算法之美》

    极客时间:https://time.geekbang.org/column/intro/126

  • 相关阅读:
    我的学习思维:有关时间的管理
    Eureka的故事,专注能让你看到别人看不到的事情
    善用思维导图来整理发散的思维
    二八原理:人才招聘中的二八原理
    二八原理:员工激励中的二八原理
    二八原理:员工的三种类型
    二八原理:你必须知悉的二八原理
    Java程序员笔试、面试题目
    String StringBuffer StringBuilder
    log4j的使用详细解析
  • 原文地址:https://www.cnblogs.com/ssh-html/p/9978733.html
Copyright © 2020-2023  润新知