zoukankan      html  css  js  c++  java
  • java数据结构——二叉树(BinaryTree)

    前面我们已经学习了一些线性结构的数据结构和算法,接下来我们开始学习非线性结构的内容。

    二叉树

    前面显示增、删、查、遍历方法,完整代码在最后面。

    /**
     * 为什么我们要学习树结构。
     * 1、有序数组插入数据项和删除数据项太慢。
     * 2、链表查找数据太慢。
     * 3、在树中能非常快速的查找、插入、删除数据,结合了有序数组和链表的优点
     * 4、暂时还不知道
     */

    结点打包类

     1 public class BinaryTree {
     2     //数据项(对象什么都可以)
     3     public long data;    
     4     //左孩子
     5     public BinaryTree leftChiled;    
     6     //右孩子
     7     public BinaryTree rightChiled;
     8     
     9     public BinaryTree(int value) {
    10         this.data = value;
    11     }
    12     
    13 }
     1 public void add(int value) {
     2         // 封装结点
     3         BinaryTree newnode = new BinaryTree(value);
     4 
     5         BinaryTree parent;// 引用父节点
     6 
     7         BinaryTree current = root;// current引用根结点
     8 
     9         if (root == null) {// 如果root为null,也就是第一次插入
    10             root = newnode;
    11             return;
    12         } else {
    13             while (true) {
    14 
    15                 parent = current;// 父节点指向指向当前节点,保存上一个结点
    16                 if (current.data > value) {
    17                     current = current.leftChiled;
    18                     if (current == null) {
    19                         parent.leftChiled = newnode;
    20                         return;
    21                     }
    22                 } else {
    23                     current = current.rightChiled;
    24 
    25                     if (current == null) {
    26                         parent.rightChiled = newnode;
    27                         return;
    28                     }
    29                 }
    30 
    31             }
    32         }
    33     }
    添加方法
     

    一、删除节点是二叉树操作中最复杂的。在删除之前首先要查找要删的节点。找到节点后,这个要删除的节点可能会有三种情况需要考虑。

    1.该节点是叶子节点,没有子节点。
    要删除叶节点,只需要改变该节点的父节点的引用值,将指向该节点的引用设置为null就可以了。
    2.该节点有一个子节点。
    改变父节点的引用,将其直接指向要删除节点的子节点。
    3.该节点有两个子节点。
    要删除有两个子节点的节点,就需要使用它的中序后继来替代该节点。
    费我九牛二虎之力还是给整出来了。
     
     1 public boolean delete(long value) {// 删除
     2         BinaryTree current = root;// current保存根结点
     3         BinaryTree parent = root;// parent保存parent的父节点
     4         boolean isLeftchild = true;
     5         while (current.data != value) {
     6             parent = current;
     7             // 进行比较,比较当前值和查找值的大小
     8             if (current.data > value) {
     9                 current = current.leftChiled;
    10                 isLeftchild = true;// true为左子树
    11             } else {
    12                 current = current.rightChiled;
    13                 isLeftchild = false;
    14             }
    15             if (current == null) {
    16                 return false;
    17             }
    18         }
    19         if (current.leftChiled == null && current.rightChiled == null) {// 第1种情况
    20             if (isLeftchild) {
    21                 parent.leftChiled = null;
    22             } else {
    23                 parent.rightChiled = null;
    24             }
    25         } else if (current.rightChiled == null) {// 第2种情况
    26             if (current == root) {
    27                 root = current.leftChiled;
    28             } else if (isLeftchild) {
    29                 parent.leftChiled = current.leftChiled;
    30             } else {
    31                 parent.rightChiled = current.leftChiled;
    32             }
    33         } else if (current.leftChiled == null) {
    34             if (current == root) {
    35                 root = current.rightChiled;
    36             } else if (isLeftchild) {
    37                 parent.leftChiled = current.rightChiled;
    38             } else {
    39                 parent.rightChiled = current.rightChiled;
    40             }
    41         } else {// 第3种情况
    42             BinaryTree successor = getSuccessor(current);// 根结点开始,successor存放中序后继结点
    43             if (current == root) {// 替换工作
    44                 root = successor;
    45             } else if (isLeftchild) {// 要删除的父节点的左子节点
    46                 parent.leftChiled = successor;
    47             } else {// 要删除的父节点的右子节点
    48                 parent.rightChiled = successor;
    49             }
    50             successor.leftChiled = current.leftChiled;// 中序后继结点引用删除的左边的结点
    51         }
    52 
    53         return true;
    54     }
    55 
    56     public BinaryTree getSuccessor(BinaryTree delBin) {// 找中序后继结点方法
    57         // delBin为要删除的结点
    58         BinaryTree successor = delBin;// successor为查找的中序后继结点
    59         BinaryTree successorParent = delBin; // successor的父节点
    60         BinaryTree current = delBin.rightChiled; // 当前开始遍历的结点
    61 
    62         while (current != null) {// 这里完成elBin.rightChiled是叶子结点
    63             successorParent = successor;// successorParent保存上一个successor的引用
    64             successor = current;// 循环完成以后,successor保存的就是中序后继结点
    65             current = current.leftChiled;
    66         }
    67         // 中序后继结点有两种情况,就是delBin.rightChiled是否为叶子结点的两种情况
    68 
    69         if (successor != delBin.rightChiled) {// elBin.rightChiled不是叶子结点,中序后继结点是左边的
    70             successorParent.leftChiled = successor.rightChiled;// 中序后继结点后面肯定只有右子节点
    71             successor.rightChiled = delBin.rightChiled;// 中序后继结点的右子节点指向要删除的右边的结点
    72             // successor.rightChiled指向要删除的rightChiled
    73             // 交换成功
    74         }
    75         return successor;
    76 
    77     }
    删除方法

    二、

     1     public BinaryTree find(int value) {// 查找
     2         // 引用当前结点,从根结点开始
     3         BinaryTree current = root;
     4         // 循环,只要查找值不等于当前结点的数据项
     5         while (current.data != value) {
     6             // 进行比较,比较当前值和查找值的大小
     7             if (current.data > value) {
     8                 current = current.leftChiled;
     9             } else {
    10                 current = current.rightChiled;
    11             }
    12             if (current == null) {
    13                 return null;
    14             }
    15 
    16         }
    17         return current;
    18     }
    查找方法

     遍历二叉树,有3种遍历方法。其中,中序遍历最为常用,因为可以让特定的数据排序输出,前面我们已经学习了递归方法,接下来我们也使用递归方法实现。

    前序遍历。
    (1)访问根结点
    (2)前序遍历左子树
    (3)前序遍历右子树
    1 public void frontOrder(BinaryTree localBin) {// 前序
    2         if (localBin != null) {// 递归结束条件
    3             System.out.println(localBin.data);
    4             frontOrder(localBin.leftChiled);
    5             frontOrder(localBin.rightChiled);
    6         }
    7     }
    前序遍历

    中序遍历。
    (1)中序遍历左子树
    (2)访问根结点
    (3)中序遍历右子树
    1 public void middleOrder(BinaryTree localBin) {// 前序
    2         if (localBin != null) {// 递归结束条件
    3             middleOrder(localBin.leftChiled);
    4             System.out.println(localBin.data);
    5             middleOrder(localBin.rightChiled);
    6         }
    7     }
    中序遍历

    后序遍历。
    (1)后序遍历左子树
    (2)后序遍历右子树
    (3)访问根结点
    1 public void endOrder(BinaryTree localBin) {// 前序
    2         if (localBin != null) {// 递归结束条件
    3             endOrder(localBin.leftChiled);
    4             endOrder(localBin.rightChiled);
    5             System.out.println(localBin.data);
    6         }
    7     }
    后序遍历

     前辈的头发秃光不是没有原因的,哈哈哈

     
      1 package binarytree;
      2 
      3 public class TestTree {
      4     // 根结点
      5     public BinaryTree root;
      6 
      7     public static void main(String[] args) {
      8         TestTree tt = new TestTree();
      9         tt.add(10);
     10         tt.add(5);
     11         tt.add(4);
     12         tt.add(6);
     13         tt.add(12);
     14         tt.add(11);
     15         tt.add(14);
     16         tt.add(13);
     17 
     18         tt.middleOrder(tt.root);
     19         tt.delete(10);
     20         System.out.println();
     21         tt.middleOrder(tt.root);
     22 
     23     }
     24 
     25     public void frontOrder(BinaryTree localBin) {// 前序
     26         if (localBin != null) {// 递归结束条件
     27             System.out.print(localBin.data + " ");
     28             frontOrder(localBin.leftChiled);
     29             frontOrder(localBin.rightChiled);
     30         }
     31     }
     32 
     33     public void middleOrder(BinaryTree localBin) {// 中序
     34         if (localBin != null) {// 递归结束条件
     35             middleOrder(localBin.leftChiled);
     36             System.out.print(localBin.data + " ");
     37             middleOrder(localBin.rightChiled);
     38         }
     39     }
     40 
     41     public void endOrder(BinaryTree localBin) {// 后序
     42         if (localBin != null) {// 递归结束条件
     43             endOrder(localBin.leftChiled);
     44             endOrder(localBin.rightChiled);
     45             System.out.print(localBin.data + " ");
     46         }
     47     }
     48 
     49     public void add(int value) {
     50         // 封装结点
     51         BinaryTree newnode = new BinaryTree(value);
     52 
     53         BinaryTree parent;// 引用父节点
     54 
     55         BinaryTree current = root;// current引用根结点
     56 
     57         if (root == null) {// 如果root为null,也就是第一次插入
     58             root = newnode;
     59             return;
     60         } else {
     61             while (true) {
     62 
     63                 parent = current;// 父节点指向指向当前节点,保存上一个结点
     64                 if (current.data > value) {
     65                     current = current.leftChiled;
     66                     if (current == null) {
     67                         parent.leftChiled = newnode;
     68                         return;
     69                     }
     70                 } else {
     71                     current = current.rightChiled;
     72 
     73                     if (current == null) {
     74                         parent.rightChiled = newnode;
     75                         return;
     76                     }
     77                 }
     78 
     79             }
     80         }
     81     }
     82 
     83     public BinaryTree find(int value) {// 查找
     84         // 引用当前结点,从根结点开始
     85         BinaryTree current = root;
     86         // 循环,只要查找值不等于当前结点的数据项
     87         while (current.data != value) {
     88             // 进行比较,比较当前值和查找值的大小
     89             if (current.data > value) {
     90                 current = current.leftChiled;
     91             } else {
     92                 current = current.rightChiled;
     93             }
     94             if (current == null) {
     95                 return null;
     96             }
     97 
     98         }
     99         return current;
    100     }
    101 
    102     public boolean delete(long value) {// 删除
    103         BinaryTree current = root;// current保存根结点
    104         BinaryTree parent = root;// parent保存parent的父节点
    105         boolean isLeftchild = true;
    106         while (current.data != value) {
    107             parent = current;
    108             // 进行比较,比较当前值和查找值的大小
    109             if (current.data > value) {
    110                 current = current.leftChiled;
    111                 isLeftchild = true;// true为左子树
    112             } else {
    113                 current = current.rightChiled;
    114                 isLeftchild = false;
    115             }
    116             if (current == null) {
    117                 return false;
    118             }
    119         }
    120         if (current.leftChiled == null && current.rightChiled == null) {// 第1种情况
    121             if (isLeftchild) {
    122                 parent.leftChiled = null;
    123             } else {
    124                 parent.rightChiled = null;
    125             }
    126         } else if (current.rightChiled == null) {// 第2种情况
    127             if (current == root) {
    128                 root = current.leftChiled;
    129             } else if (isLeftchild) {
    130                 parent.leftChiled = current.leftChiled;
    131             } else {
    132                 parent.rightChiled = current.leftChiled;
    133             }
    134         } else if (current.leftChiled == null) {
    135             if (current == root) {
    136                 root = current.rightChiled;
    137             } else if (isLeftchild) {
    138                 parent.leftChiled = current.rightChiled;
    139             } else {
    140                 parent.rightChiled = current.rightChiled;
    141             }
    142         } else {// 第3种情况
    143             BinaryTree successor = getSuccessor(current);// 根结点开始,successor存放中序后继结点
    144             if (current == root) {// 替换工作
    145                 root = successor;
    146             } else if (isLeftchild) {// 要删除的父节点的左子节点
    147                 parent.leftChiled = successor;
    148             } else {// 要删除的父节点的右子节点
    149                 parent.rightChiled = successor;
    150             }
    151             successor.leftChiled = current.leftChiled;// 中序后继结点引用删除的左边的结点
    152         }
    153 
    154         return true;
    155     }
    156 
    157     public BinaryTree getSuccessor(BinaryTree delBin) {// 找中序后继结点方法
    158         // delBin为要删除的结点
    159         BinaryTree successor = delBin;// successor为查找的中序后继结点
    160         BinaryTree successorParent = delBin; // successor的父节点
    161         BinaryTree current = delBin.rightChiled; // 当前开始遍历的结点
    162 
    163         while (current != null) {// 这里完成elBin.rightChiled是叶子结点
    164             successorParent = successor;// successorParent保存上一个successor的引用
    165             successor = current;// 循环完成以后,successor保存的就是中序后继结点
    166             current = current.leftChiled;
    167         }
    168         // 中序后继结点有两种情况,就是delBin.rightChiled是否为叶子结点的两种情况
    169 
    170         if (successor != delBin.rightChiled) {// elBin.rightChiled不是叶子结点,中序后继结点是左边的
    171             successorParent.leftChiled = successor.rightChiled;// 中序后继结点后面肯定只有右子节点
    172             successor.rightChiled = delBin.rightChiled;// 中序后继结点的右子节点指向要删除的右边的结点
    173             // successor.rightChiled指向要删除的rightChiled
    174             // 交换成功
    175         }
    176         return successor;
    177 
    178     }
    179 }
    complete code
  • 相关阅读:
    寻找金秋
    两个周末,两个湖
    桂花林上,再读“六项精进”
    锄奸杜幸,穷寇勿追
    招聘所见思考
    Xufun’s Node.js Primer
    我的软件过程,一年再读
    企业的生命期限,和组织的危机感
    头痛,偷闲,拾黄叶
    喝酒这件事,和等绿灯的习惯
  • 原文地址:https://www.cnblogs.com/hardhp74520/p/11312544.html
Copyright © 2011-2022 走看看