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
  • 相关阅读:
    Longest Palindromic Substring
    PayPal MLSE job description
    Continuous Median
    Remove Duplicates From Linked List
    Valid IP Address
    Longest substring without duplication
    Largest range
    Subarray sort
    Multi String Search
    Suffix Trie Construction
  • 原文地址:https://www.cnblogs.com/hardhp74520/p/11312544.html
Copyright © 2011-2022 走看看