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

  • 相关阅读:
    UVa OJ 148 Anagram checker (回文构词检测)
    UVa OJ 134 LoglanA Logical Language (Loglan逻辑语言)
    平面内两条线段的位置关系(相交)判定与交点求解
    UVa OJ 130 Roman Roulette (罗马轮盘赌)
    UVa OJ 135 No Rectangles (没有矩形)
    混合函数继承方式构造函数
    html5基础(第一天)
    js中substr,substring,indexOf,lastIndexOf,split等的用法
    css的textindent属性实现段落第一行缩进
    普通的css普通的描边字
  • 原文地址:https://www.cnblogs.com/Mufasa/p/11289057.html
Copyright © 2011-2022 走看看