zoukankan      html  css  js  c++  java
  • 数据结构-二叉搜索树Java实现

    1,Node.java

    生成基础二叉树的结构

     1 package com.cnblogs.mufasa.searchTree;
     2 
     3 /**
     4  * 节点配置父+左+右
     5  */
     6 public class Node{
     7     Node parent;
     8     Node leftChild;
     9     Node rightChild;
    10     int val;
    11     public Node(Node parent, Node leftChild, Node rightChild,int val) {
    12         super();
    13         this.parent = parent;
    14         this.leftChild = leftChild;
    15         this.rightChild = rightChild;
    16         this.val = val;
    17     }
    18 
    19     public Node(int val){
    20         this(null,null,null,val);
    21     }
    22 
    23     public Node(Node node,int val){
    24         this(node,null,null,val);
    25     }
    26 }
    View Code

    图1 Node.java结构

    2,SearchBinaryTree.java

    在原有二叉树的结构上,进行搜索二叉树的功能扩充:

    ①数据增加:递归版本插入、迭代版本

    ②数据删除:

    ③数据查找:

    ④数据遍历:前中后

      1 package com.cnblogs.mufasa.searchTree;
      2 
      3 
      4 
      5 public class SearchBinaryTree {
      6 
      7     private Node root;
      8     private int size;
      9     public SearchBinaryTree() {
     10         super();
     11     }
     12 
     13     /**
     14      * 增加节点
     15      * @param val
     16      * @return
     17      */
     18     public boolean add(int val) {
     19         if(root == null){//初始节点为空
     20             root = new Node(val);
     21             size++;
     22             return true;
     23         }
     24         //初始节点不为空
     25         Node node = getAdapterNode(root, val);
     26         Node newNode = new Node(val);
     27         if(node.val > val){
     28             node.leftChild = newNode;
     29             newNode.parent = node;
     30         }else if(node.val < val){
     31             node.rightChild = newNode;
     32             newNode.parent = node;
     33         }else{
     34             return false;//增加数据和搜索二叉树中原有数据相同不符合基本限定条件
     35         }
     36         size++;
     37         return true;
     38     }
     39 
     40     /**
     41      * 获取最合适的插入节点
     42      * @param node
     43      * @param val
     44      * @return
     45      */
     46     private Node getAdapterNode(Node node,int val){
     47         //该节点为空
     48         if(node == null){
     49             return node;
     50         }
     51 
     52         // 往左子树中插入,但没左子树,则返回
     53         if(node.val > val && node.leftChild == null){
     54             return node;
     55         }
     56 
     57         // 往右子树中插入,但没右子树,也返回
     58         if(node.val < val && node.rightChild == null){
     59             return node;
     60         }
     61 
     62         // 该节点是叶子节点,则返回
     63         if(node.leftChild == null && node.rightChild == null){
     64             return node;
     65         }
     66 
     67         //节点可以继续向下,直接递归调用
     68         if(node.val > val && node.leftChild != null){
     69             return getAdapterNode(node.leftChild, val);
     70         }else if(node.val < val && node.rightChild != null){
     71             return getAdapterNode(node.rightChild, val);
     72         }else{
     73             return node;
     74         }
     75     }
     76 
     77     /**
     78      * 进行迭代增加元素
     79      * @param val
     80      * @return
     81      */
     82     public boolean put(int val){
     83         return putVal(root,val);
     84     }
     85 
     86     /**
     87      *直接循环搜索目标节点进行数据增加
     88      * @param node
     89      * @param val
     90      * @return
     91      */
     92     private boolean putVal(Node node,int val){
     93         if(node == null){// 初始化根节点
     94             node = new Node(val);
     95             root = node;
     96             size++;
     97             return true;
     98         }
     99         //节点非空
    100         Node temp = node;
    101         Node p;
    102         int t;
    103         /**
    104          * 通过do while循环迭代获取最佳节点,
    105          */
    106         do{
    107             p = temp;
    108             t = temp.val-val;
    109             if(t > 0){
    110                 temp = temp.leftChild;
    111             }else if(t < 0){
    112                 temp = temp.rightChild;
    113             }else{
    114                 temp.val = val;//增加数据和搜索二叉树中原有数据相同不符合基本限定条件
    115                 return false;
    116             }
    117         }while(temp != null);
    118 
    119         Node newNode = new Node(p, val);
    120         if(t > 0){
    121             p.leftChild = newNode;
    122         }else if(t < 0){
    123             p.rightChild = newNode;
    124         }
    125         size++;
    126         return true;
    127     }
    128 
    129     /**
    130      * 节点删除
    131      * @param val
    132      * @return
    133      */
    134     public boolean delete(int val){
    135         Node node = getNode(val);
    136         if(node == null){//没有该节点
    137             return false;
    138         }
    139         Node parent = node.parent;
    140         Node leftChild = node.leftChild;
    141         Node rightChild = node.rightChild;
    142 
    143         //以下所有子节点为空的情况,则表明删除的节点是【叶节点】
    144         if(leftChild == null && rightChild == null){//没有子节点
    145             if(parent != null){
    146                 if(parent.leftChild == node){
    147                     parent.leftChild = null;
    148                 }else if(parent.rightChild == node){
    149                     parent.rightChild = null;
    150                 }
    151             }else{//不存在父节点,则表明删除节点为【根节点】,直接返回空
    152                 root = null;
    153             }
    154             node = null;
    155             return true;
    156 
    157         }else if(leftChild == null && rightChild != null){// 只有右节点
    158             if(parent != null && parent.val > val){// 存在父节点,且node位置为父节点的左边
    159                 parent.leftChild = rightChild;
    160             }else if(parent != null && parent.val < val){// 存在父节点,且node位置为父节点的右边
    161                 parent.rightChild = rightChild;
    162             }else{//父节点不存在!!!
    163                 root = rightChild;
    164             }
    165             node = null;
    166             return true;
    167 
    168         }else if(leftChild != null && rightChild == null){// 只有左节点
    169             if(parent != null && parent.val > val){// 存在父节点,且node位置为父节点的左边
    170                 parent.leftChild = leftChild;
    171             }else if(parent != null && parent.val < val){// 存在父节点,且node位置为父节点的右边
    172                 parent.rightChild = leftChild;
    173             }else{//父节点不存在!!!
    174                 root = leftChild;
    175             }
    176             node = null;
    177             return true;
    178 
    179         }else if(leftChild != null && rightChild != null){// 两个子节点都存在,相当于直接替换节点
    180             Node successor = getSuccessor(node);// 这种情况,一定存在后继节点
    181             int temp = successor.val;
    182             boolean delete = delete(temp);
    183             if(delete){
    184                 node.val = temp;
    185             }
    186             successor = null;
    187             return true;
    188         }
    189         return false;
    190     }
    191 
    192     /**
    193      *
    194      * @param node
    195      * @return
    196      */
    197     private Node getSuccessor(Node node){
    198         if(node.rightChild != null){//肯定不为空
    199             Node rightChild = node.rightChild;
    200             while(rightChild.leftChild != null){//不断的向左转向搜索数值
    201                 rightChild = rightChild.leftChild;
    202             }
    203             return rightChild;
    204         }
    205         //右节点为空这个不存在啊!!!
    206         Node parent = node.parent;
    207         while(parent != null && (node == parent.rightChild)){
    208             node = parent;
    209             parent = parent.parent;
    210         }
    211         return parent;
    212     }
    213 
    214 
    215     /**
    216      * 搜索节点
    217      * @param val
    218      * @return
    219      */
    220     public Node getNode(int val){
    221         Node temp = root;
    222         int t;
    223         do{//直接使用循环遍历的方法
    224             t = temp.val-val;
    225             if(t > 0){
    226                 temp = temp.leftChild;
    227             }else if(t < 0){
    228                 temp = temp.rightChild;
    229             }else{
    230                 return temp;
    231             }
    232         }while(temp != null);
    233         return null;
    234     }
    235 
    236     /**
    237      * 节点删除
    238      * @param val
    239      * @return
    240      */
    241     public boolean remove(int val){
    242         Node node = getNode(val);
    243         if(node == null){
    244             return false;
    245         }
    246 
    247         if(node.leftChild == null){// 1、左节点不存在,右节点可能存在,包含两种情况  ,两个节点都不存在和只存在右节点
    248             transplant(node, node.rightChild);
    249         }else if(node.rightChild == null){//2、左孩子存在,右节点不存在
    250             transplant(node, node.leftChild);
    251         }else{// 3、两个节点都存在
    252             Node successor = getSuccessor(node);// 得到node后继节点
    253             if(successor.parent != node){// 后继节点存在node的右子树中。
    254                 transplant(successor, successor.rightChild);// 用后继节点的右子节点替换该后继节点
    255                 successor.rightChild = node.rightChild;// 将node节点的右子树赋给后继节点的右节点,即类似后继与node节点调换位置
    256                 successor.rightChild.parent = successor;// 接着上一步  给接过来的右节点的父引用复制
    257             }
    258             transplant(node, successor);
    259             successor.leftChild = node.leftChild;
    260             successor.leftChild.parent = successor;
    261         }
    262         return true;
    263     }
    264     /**
    265      * 将child节点替换node节点
    266      * @param node    要删除的节点
    267      * @param child   node节点的子节点
    268      */
    269     private void transplant(Node node,Node child){
    270         /**
    271          * 1、先判断 node是否存在父节点
    272          *    1、不存在,则child替换为根节点
    273          *    2、存在,则继续下一步
    274          * 2、判断node节点是父节点的那个孩子(即判断出 node是右节点还是左节点),
    275          *    得出结果后,将child节点替换node节点 ,即若node节点是左节点 则child替换后 也为左节点,否则为右节点
    276          * 3、将node节点的父节点置为child节点的父节点
    277          */
    278 
    279         if(node.parent == null){
    280             this.root = child;
    281         }else if(node.parent.leftChild == node){
    282             node.parent.leftChild = child;
    283         }else if(node.parent.rightChild == node){
    284             node.parent.rightChild = child;
    285         }
    286         if(child != null){
    287             child.parent = node.parent;
    288         }
    289     }
    290 
    291     public void print(int type){//方法的重载
    292         if(type==0){//前序
    293             printPre(root);
    294         }else if(type==1){
    295             printMid(root);
    296         }else if(type==2){
    297             printEnd(root);
    298         }
    299     }
    300 
    301     private void printPre(Node root){//前序遍历
    302         if(root != null){
    303             System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
    304             printPre(root.leftChild);
    305             printPre(root.rightChild);
    306         }
    307     }
    308 
    309     private void printMid(Node root){//中序遍历
    310         if(root != null){
    311             printMid(root.leftChild);
    312             System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
    313             printMid(root.rightChild);
    314         }
    315     }
    316 
    317     private void printEnd(Node root){//后序遍历
    318         if(root != null){
    319             printEnd(root.leftChild);
    320             printEnd(root.rightChild);
    321             System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
    322         }
    323     }
    324 
    325 }
    View Code

     

    图2 SearchBinaryTree.java结构

    3,JavaDemo.java

     1 package com.cnblogs.mufasa.searchTree;
     2 
     3 public class JavaDemo {
     4     public static void main(String[] args) {
     5         SearchBinaryTree tree=new SearchBinaryTree();
     6         tree.add(5);
     7         tree.add(1);
     8         tree.add(100);
     9         tree.add(50);
    10         tree.add(22);
    11         tree.add(48);
    12         tree.print(2);
    13     }
    14 }
    View Code

    4,特别鸣谢

    https://www.cnblogs.com/qm-article/p/9279655.html

  • 相关阅读:
    基于mybatis的crud demo
    事务的隔离级别
    spring中ioc的实现
    spring中xml配置文件
    spring中AOP的实现
    mybatis框架
    基于Mapreduce的并行Dijkstra算法执行过程分析
    算法技巧:位运算 逻辑运算
    day04_09 while循环03
    day04_08 while循环02
  • 原文地址:https://www.cnblogs.com/Mufasa/p/11289057.html
Copyright © 2011-2022 走看看