• 日常学习随笔-用链表的形式实现普通二叉树的新增、查找、遍历(前、中、后序)等基础功能(侧重源码+说明)


    一、二叉树

    1、二叉树的概念

    二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree),其次序不能任意颠倒。

    2、性质

    (1)若二叉树的层次从0开始,则在二叉树的第i层至多有2^i个结点(i>=0);

    (2)高度为k的二叉树最多有2^(k+1) - 1个结点(k>=-1)。 (空树的高度为-1);

    (3)对任何一棵二叉树,如果其叶子结点(度为0)数为m, 度为2的结点数为n, 则m = n + 1。

    二、二叉树的几种类型

    这里就不多介绍了,目前的进度了解还不够深入,后续继续逐步研究,下面提供一个其他博主介绍的网址:

    https://www.cnblogs.com/love-yh/p/7423301.html

    三、给出一个自定义的二叉树的案例(普通二叉树)

    二叉树类:MyTreeDefin.java

      1 package com.xfwl.algorithmAnalysis.trees;
      2 /**
      3  * 二叉树结构分析
      4  * @function  日常学习测试
      5  * @author 小风微凉
      6  * @time  2018-5-20 下午12:28:50
      7  */
      8 public class MyTreeDefin<T extends Comparable<? super T>>{
      9     /**
     10      * 每棵树都有一个根节点
     11      */
     12     private BinaryNode<T> root;
     13     /**
     14      * 整棵树的节点个数
     15      */
     16     private int nodeCount;
     17     /**
     18      * 二叉树构造器
     19      */
     20     public MyTreeDefin(){
     21         this.reset();
     22     }
     23     /**
     24      * 重置整棵树的结构
     25      */
     26     private void reset(){
     27         //二叉树的根节点初始化
     28         root=null;
     29         //二叉树的节点总数:归0
     30         this.nodeCount=0;
     31     }
     32     /**
     33      * 清空整棵二叉树
     34      * @return
     35      */
     36     public boolean makeEmpty(){
     37         this.reset();
     38         return this.isEmpty();
     39     }
     40     /**
     41      * 获取树的节点个数
     42      * @return
     43      */
     44     public int getSize(){
     45         return this.nodeCount;
     46     }
     47     /**
     48      * 判断整棵树是否为空树
     49      * @return
     50      */
     51     public boolean isEmpty(){
     52         return this.nodeCount==0?true:false;
     53     }
     54     /**
     55      * 判断二叉树中指定节点后面是否包含指定数据
     56      * @param target  检索数据target
     57      * @param node    指定的节点(包含当前节点)
     58      * @return
     59      */
     60     public boolean contains(T target,BinaryNode<T> node){
     61         //判空检查
     62         if(node==null){
     63             return false;
     64         }
     65         //先和当前节点的数据比较
     66         int compareResult=target.compareTo(node.elem);
     67         if(compareResult>0){//进入右子树中继续判断
     68             return contains(target,node.right);
     69         }else if(compareResult<0){//进入左子树中继续判断
     70             return contains(target,node.left);
     71         }else{//相等
     72             return true;
     73         }
     74     }
     75     /**
     76      * 从根节点开始查找整棵树是否包含指定的数据
     77      * @param target 检索数据target
     78      * @return
     79      */
     80     public boolean contains(T target){
     81         return this.contains(target, this.root);
     82     }
     83     /**
     84      * 查找整棵树中的最小数据
     85      * 左子树最后一个节点数据
     86      * @return
     87      */
     88     public T findMin(){
     89         return this.findMin(this.root).elem;
     90     }
     91     /**
     92      * 查找指定树节点下面的最小节点[查找指定节点后面的最小节点]
     93      * @param node    指定的节点
     94      * @return
     95      */
     96     public BinaryNode<T> findMin(BinaryNode<T> node){
     97         //如果节点为空
     98         if(node==null){
     99             return null;
    100         }else if(node.left==null){//递归基准情况
    101             return node;
    102         }else{//递归流程
    103             return findMin(node.left);
    104         }
    105     }
    106     /**
    107      * 查找指定树节点下面的最大节点[最大的数据在右子树的最深叶子节点]
    108      * @param node   指定的查找起点节点
    109      * @return
    110      */
    111     public BinaryNode<T> findMax(BinaryNode<T> node){
    112         //如果节点为空
    113         if(node==null){
    114             return null;
    115         }else if(node.right==null){//递归基准情况
    116             return node;
    117         }else{//递归流程
    118             return findMax(node.right);
    119         }
    120     }
    121     /**
    122      * 查找整棵树中的最大数据
    123      * @return
    124      */
    125     public T findMax(){        
    126         return this.findMax(this.root).elem;
    127     }
    128     /**
    129      * 为二叉树添加新的节点(对外)
    130      * @param data 要添加的数据
    131      * @return
    132      */
    133     public BinaryNode<T> add(T data){
    134         if(this.isEmpty()){
    135             this.nodeCount++;
    136             this.root=new BinaryNode<>(data,null,null);
    137             return this.root;
    138         }else{
    139             this.nodeCount++;
    140             return this.add(data, this.root);
    141         }        
    142     }
    143     /**
    144      * 为二叉树添加新的节点(对内)
    145      * @param data 要添加的数据
    146      * @param curNode 要添加的节点(递归比较)
    147      */
    148     private BinaryNode<T> add(T data,BinaryNode<T> curNode){
    149         //如果节点不存在:递归基准情况
    150         if(curNode==null){
    151             return new BinaryNode<>(data,null,null);
    152         }
    153         //按照:左>根>右  的大小顺序插入二叉树中
    154         //比较起点:先和根节点数据比较
    155         int compareResult=data.compareTo(curNode.elem);
    156         if(compareResult<0){//走左子树
    157             System.out.println("左<--");
    158             curNode.left=this.add(data,curNode.left);
    159         }else if(compareResult>0){//走右子树
    160             System.out.println("-->右");
    161             curNode.right=this.add(data,curNode.right);
    162         }else{//如果添加的节点数据和当前比较的根节点相同
    163             //不做任何处理,可在此继续扩展
    164         }                
    165         //返回的是根节点
    166         return curNode;
    167     }
    168     /**
    169      * 非递归添加树节点
    170      * @param data 节点数据
    171      * @return
    172      */
    173     public void  push(T data){
    174         if(this.isEmpty()){//空树结构
    175             this.nodeCount++;
    176             this.root=new BinaryNode<>(data,null,null);
    177         }else{//至少含有一个根节点
    178             BinaryNode<T> tmpNode =this.root;
    179             System.out.println("--------------------根节点数据:"+tmpNode.elem+",--------------------");
    180             while(true){
    181                 System.out.println("while----:tmpNode.elem="+tmpNode.elem+",data="+data);
    182                 int compareResult=data.compareTo(tmpNode.elem);
    183                 if(compareResult<0){//走左子树
    184                     System.out.println("左<--");
    185                     if(tmpNode.left==null){
    186                         tmpNode.left=new BinaryNode<>(data,null,null);
    187                         break;
    188                     }
    189                     tmpNode=tmpNode.left;
    190                 }else if(compareResult>0){//走右子树
    191                     System.out.println("-->右");
    192                     if(tmpNode.right==null){
    193                         tmpNode.right=new BinaryNode<>(data,null,null);
    194                         break;
    195                     }
    196                     tmpNode=tmpNode.right;
    197                 }else{//替换当前节点数据(压入相同数据,没改变)
    198                     //也即不做处理
    199                     break;
    200                 }
    201             }
    202             this.nodeCount++;
    203         }
    204     }
    205     /**
    206      * 移除二叉树中根节点后面的指定数据(所在的节点)
    207      * @param data  指定的数据
    208      */
    209     public BinaryNode<T> remove(T data){
    210         return this.remove(data, this.root);
    211     }
    212     /**
    213      * [删除是最难的:慢慢琢磨-琢磨好了-以后另开一篇]
    214      * 移除二叉树中指定节点后面的指定数据(所在的节点)
    215      * @param node  指定的节点
    216      * @param data  指定的数据
    217      */
    218     public BinaryNode<T> remove(T data,BinaryNode<T> node){
    219         //节点判断
    220         if(node==null){
    221             return null;
    222         }
    223         //开始比较
    224         int compareResult=data.compareTo(node.elem);
    225         if(compareResult==0){//找到基准情况[刚好找到要删除的数据节点]
    226             /**
    227              * 找到这个节点
    228              */
    229         }
    230         //....算了,考虑的头比较痛,下次再开一篇专门研究二叉树删除的案例
    231         return null;
    232     }
    233     /**
    234      * 打印树结构信息
    235      * @param index  遍历的类型
    236      * 一般用到的遍历方式有三种:
    237      * (1)前序遍历    0
    238      * (2)中序遍历    1
    239      * (3)后序遍历    2
    240      */
    241     public void printTree(int index){
    242         String type=(index==0?"前序":index==1?"中序":"后序")+"遍历";
    243         System.out.println("------------【开始遍历打印·"+type+"】------------");
    244         switch(index){
    245             case 0:preOrder(this.root);break;
    246             case 1:inOrder(this.root);break;
    247             case 2:postOrder(this.root);break;
    248         } 
    249         System.out.println("------------【打印结束】------------");        
    250     }
    251     /**
    252      * 前序遍历
    253      * @param node  遍历的起始节点
    254      * 采用递归思想
    255      *  对左子节点进行遍历
    256      *  对右子节点进行遍历
    257      *  递归基值是node是否是null
    258      */
    259      private void preOrder(BinaryNode<T> node)
    260      {
    261         if(node==null){
    262             return;
    263         }else{
    264             System.out.print(node.elem+" ");//输出数据节点信息
    265             preOrder(node.left);
    266             preOrder(node.right);
    267         }
    268      }
    269     /**
    270      * 中序遍历
    271      * @param node
    272      */
    273     private void inOrder(BinaryNode<T> node){
    274         if(node==null){
    275             return;
    276         }else{
    277             inOrder(node.left);
    278             System.out.print(node.elem+" ");
    279             inOrder(node.right);
    280         }
    281     }
    282     /**
    283      * 后序遍历
    284      * @param node
    285      */
    286     private void postOrder(BinaryNode<T> node){
    287         if(node==null){
    288             return;
    289         }else{
    290             postOrder(node.left);
    291             postOrder(node.right);
    292             System.out.print(node.elem+" ");
    293         }
    294     }
    295     /**
    296      * 获取指定节点的数据
    297      * @param node
    298      * @return
    299      */
    300     public T getElem(BinaryNode<T> node){
    301         if(node==null){
    302             return null;
    303         }
    304         return node.elem;
    305     }
    306     /**
    307      * 内置一个树节点类
    308      */
    309     private static class BinaryNode<T>{
    310         /**
    311          * 树节点存放数据域
    312          */
    313         T elem;
    314         /**
    315          * 左子树节点域
    316          */
    317         BinaryNode<T> left;
    318         /**
    319          * 右子树节点域
    320          */
    321         BinaryNode<T> right;
    322         /**
    323          * 构造器
    324          */
    325         public BinaryNode(T elem,BinaryNode<T> left,BinaryNode<T> right){
    326             this.elem=elem;
    327             this.left=left;
    328             this.right=right;
    329         }        
    330     }
    331 }
    332  

    测试类:Test.java

     1 package com.xfwl.algorithmAnalysis.trees;
     2 
     3 public class Test {
     4     /**
     5      * @param args
     6      */
     7     public static void main(String[] args) {
     8         //创建一棵树
     9         MyTreeDefin<Integer> tree=new MyTreeDefin<>();
    10         //压入数据
    11         tree.push(5);
    12         tree.push(2);
    13         tree.push(4);
    14         tree.push(8);
    15         tree.push(7);
    16         tree.push(10);
    17         tree.push(3);
    18         tree.push(9);
    19         tree.push(6);
    20         tree.push(1);
    21         System.out.println(tree.getSize());
    22         //开始遍历显示
    23         tree.printTree(0);
    24         tree.printTree(1);
    25         tree.printTree(2);
    26         //删除
    27     }
    28 }

    测试结果:

    --------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=2<--
    --------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=4<--
    while----:tmpNode.elem=2,data=4
    -->--------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=8
    -->--------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=7
    -->while----:tmpNode.elem=8,data=7<--
    --------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=10
    -->while----:tmpNode.elem=8,data=10
    -->--------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=3<--
    while----:tmpNode.elem=2,data=3
    -->while----:tmpNode.elem=4,data=3<--
    --------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=9
    -->while----:tmpNode.elem=8,data=9
    -->while----:tmpNode.elem=10,data=9<--
    --------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=6
    -->while----:tmpNode.elem=8,data=6<--
    while----:tmpNode.elem=7,data=6<--
    --------------------根节点数据:5,--------------------
    while----:tmpNode.elem=5,data=1<--
    while----:tmpNode.elem=2,data=1<--
    10
    ------------【开始遍历打印·前序遍历】------------
    5 2 1 4 3 8 7 6 10 9 ------------【打印结束】------------
    ------------【开始遍历打印·中序遍历】------------
    1 2 3 4 5 6 7 8 9 10 ------------【打印结束】------------
    ------------【开始遍历打印·后序遍历】------------
    1 3 4 2 6 7 9 10 8 5 ------------【打印结束】------------

    四、总结一下

      最近比较忙,学习进度明显感到有点延迟了,还是得抓紧时间啊!上面的测试例子并没有写“二叉树的删除”功能,删除也比较麻烦,分为很多种情形,需要仔细分析,此篇就不在分析说明了,以后再慢慢研究,要学的东西还很多,慢慢来吧!

  • 相关阅读:
    网络编程[28]
    网络编程[30]
    网络编程[20]
    网络编程[29]
    网络编程[19]
    网络编程[15]
    网络编程[12]
    hdu 3802【Ipad,IPhone】
    hdu 2616【Kill the monster】
    hdu 1026【Ignatius and the Princess I】
  • 原文地址:https://www.cnblogs.com/newwind/p/9094937.html
Copyright © 2020-2023  润新知