java实现二叉搜索树

开门见山,首先来理解一下什么是二叉搜索树:也叫二叉排序树,是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。空树也是二叉搜索树。
       简单的说,二叉搜索树就是一课二叉树,每个父节点都一定大于等于其左孩子且小于等于它的右孩子。

       首先,创建一个节点类,Node,这个类需要有它左右孩子节点的引用,同时还应该有节点要存储的数据,为了简单起见,这里我只是用了一个index的整形数作为要保存的内容。

Java代码   收藏代码
  1. public class Node {  
  2.     private int index;  
  3.     private Node leftChild;  
  4.     private Node rightChild;  
  5.   
  6.     public Node() {  
  7.     }  
  8.   
  9.     public Node(int index) {  
  10.         super();  
  11.         this.index = index;  
  12.     }  
  13.   
  14.     public int getIndex() {  
  15.         return index;  
  16.     }  
  17.   
  18.     public void setIndex(int index) {  
  19.         this.index = index;  
  20.     }  
  21.   
  22.     public Node getLeftChild() {  
  23.         return leftChild;  
  24.     }  
  25.   
  26.     public void setLeftChild(Node leftChild) {  
  27.         this.leftChild = leftChild;  
  28.     }  
  29.   
  30.     public Node getRightChild() {  
  31.         return rightChild;  
  32.     }  
  33.   
  34.     public void setRightChild(Node rightChild) {  
  35.         this.rightChild = rightChild;  
  36.     }  
  37.   
  38. }  

       接着,我们创建一个二叉树的类,BinaryTree,它只有一个根节点。里面主要有插入节点,查找节点的方法,删除节点的方法。
       查找的过程:从根节点开始,根节点为当前节点,判断要查找的内容与当前节点的内容的大小关系,若查找值小于等于当前节点的内容值,往左子树方向查找,反之往右子树查找。改变当前节点的指向对象(指向要查找的那个方向的当前节点的孩子节点),重复上诉操作,直至找到节点或者到树的底部。
       插入节点跟查找节点类似,用同样的方式找到要插入的节点的恰当的插入位置,把节点插入(即使上一级的节点的左/右孩子节点指向该要插入的节点)
       删除节点的操作:分为三种情况,第一:该节点是叶子节点,找出来直接删除即刻;第二:该节点有一个孩子节点,找出节点,删除节点并让其父节点的左/右孩子节点引用指向删除的节点的孩子节点。第三:该节点有两个孩子节点,找出节点,然后找到该节点的直接后继节点(即中序遍历时,紧跟在这个节点后面的那个节点),并用这个节点代替删除的节点

Java代码   收藏代码
  1. public class BinaryTree {  
  2.     private Node root;  
  3.   
  4.     public BinaryTree() {  
  5.     }  
  6.   
  7.     public BinaryTree(Node root) {  
  8.         this.root = root;  
  9.     }  
  10.   
  11.     public Node getRoot() {  
  12.         return root;  
  13.     }  
  14.   
  15.     public void setRoot(Node root) {  
  16.         this.root = root;  
  17.     }  
  18.   
  19.     /** 
  20.      * 寻找节点 
  21.      *  
  22.      * @param node 
  23.      */  
  24.     public Node find(int index) {  
  25.         if (this.root.getIndex() == index) {  
  26.             return this.root;  
  27.         }  
  28.         Node current = this.root;  
  29.         while (current != null) {  
  30.             int temp_index = current.getIndex();  
  31.             // 判断查询方向  
  32.             if (temp_index >= index) {// 左子树  
  33.                 current = current.getLeftChild();  
  34.             } else {  
  35.                 current = current.getRightChild();  
  36.             }  
  37.             // 判断是否匹配当前节点  
  38.             if (current != null && current.getIndex() == index) {// 匹配则返回  
  39.                 return current;  
  40.             }  
  41.         }  
  42.         return null;  
  43.     }  
  44.   
  45.     /** 
  46.      * 找到要找的节点的父节点 
  47.      *  
  48.      * @param index 
  49.      * @return 
  50.      */  
  51.     private Node findParent(int index) {  
  52.         if (this.root.getIndex() == index) {  
  53.             return this.root;  
  54.         }  
  55.         Node current = this.root;  
  56.         Node parent = null;  
  57.         while (current != null) {  
  58.             parent = current;  
  59.             int temp_index = current.getIndex();  
  60.             // 判断查询方向  
  61.             if (temp_index >= index) {// 左子树  
  62.                 current = current.getLeftChild();  
  63.             } else {  
  64.                 current = current.getRightChild();  
  65.             }  
  66.             // 判断是否匹配当前节点  
  67.             if (current != null && current.getIndex() == index) {// 匹配则返回  
  68.                 return parent;  
  69.             }  
  70.         }  
  71.         return null;  
  72.     }  
  73.   
  74.     /** 
  75.      * 删除节点 
  76.      *  
  77.      * @param node 
  78.      */  
  79.     public void delete(Node node) {  
  80.         int index = node.getIndex();  
  81.         Node target = find(index);  
  82.         if (target == null) {  
  83.             System.out.println("节点不存在");  
  84.             return;  
  85.         }  
  86.         // 取得目标节点的父节点  
  87.         Node parent = this.findParent(index);  
  88.         // 目标节点左孩子  
  89.         Node left_temp = target.getLeftChild();  
  90.         // 目标节点右孩子  
  91.         Node right_temp = target.getRightChild();  
  92.   
  93.         if (target.getLeftChild() != null && target.getRightChild() != null) {// 有两个孩子节点  
  94.             // 目标节点直接左孩子  
  95.             Node direct_leftChild = left_temp;  
  96.             // 目标节点直接左孩子的父节点  
  97.             Node direct_leftChild_p = target;  
  98.             // 找到目标节点的直接左孩子节点以及记录该孩子节点的父节点  
  99.             while (direct_leftChild.getLeftChild() != null) {  
  100.                 direct_leftChild_p = direct_leftChild;  
  101.                 direct_leftChild = direct_leftChild.getLeftChild();  
  102.             }  
  103.             // 执行删除操作  
  104.             target = null;  
  105.             if (parent.getLeftChild().getIndex() == index) {  
  106.                 parent.setLeftChild(direct_leftChild);  
  107.             }  
  108.             if (parent.getRightChild().getIndex() == index) {  
  109.                 parent.setRightChild(direct_leftChild);  
  110.             }  
  111.             if (direct_leftChild_p.getRightChild() != null) {  
  112.                 direct_leftChild.setRightChild(direct_leftChild_p  
  113.                         .getRightChild());  
  114.             }  
  115.         } else {// 节点是叶子节点或者只有一个子节点的情况  
  116.             target = null;  
  117.             // 判断被删除的节点是其父节点的哪个孩子  
  118.             if (parent.getLeftChild().getIndex() == index) {// 左孩子  
  119.                 // 从新给左孩子设值(为了满足有单个孩子的情况,做了左右孩子值是否为空的判断)  
  120.                 parent.setLeftChild(left_temp == null ? right_temp : left_temp);  
  121.             }  
  122.             if (parent.getRightChild().getIndex() == index) {// 右孩子  
  123.                 // 同上  
  124.                 parent.setRightChild(right_temp == null ? left_temp  
  125.                         : right_temp);  
  126.             }  
  127.         }  
  128.     }  
  129.   
  130.     /** 
  131.      * 添加节点 
  132.      *  
  133.      * @param node 
  134.      */  
  135.     public void insert(Node node) {  
  136.         if (this.root == null) {// 根节点不存在  
  137.             this.root = node;  
  138.         } else {  
  139.             Node current = this.root;  
  140.             while (true) {  
  141.                 Node temp = null;  
  142.                 if (current.getIndex() > node.getIndex()) {// 左子树  
  143.                     temp = current.getLeftChild();  
  144.                     if (temp == null) {  
  145.                         current.setLeftChild(node);  
  146.                         return;  
  147.                     }  
  148.                 } else {  
  149.                     temp = current.getRightChild();  
  150.                     if (temp == null) {  
  151.                         current.setRightChild(node);  
  152.                         return;  
  153.                     }  
  154.                 }  
  155.                 current = temp;  
  156.             }  
  157.         }  
  158.     }  
  159.   
  160.     public void print() {  
  161.         inorder_traversal(this.root, 1);// 中序遍历的结果是一个有序的序列  
  162.     }  
  163.   
  164.     /** 
  165.      * 先序遍历 
  166.      *  
  167.      * @param node 
  168.      * @param level 
  169.      */  
  170.     private void preorder_traversal(Node node, int level) {// 先序遍历  
  171.         for (int i = 0; i < level; i++) {  
  172.             System.out.print("-");  
  173.         }  
  174.         System.out.println(node.getIndex());  
  175.         int lev = level + 1;  
  176.         if (node.getLeftChild() != null) {  
  177.             preorder_traversal(node.getLeftChild(), lev);  
  178.         }  
  179.         if (node.getRightChild() != null) {  
  180.             inorder_traversal(node.getRightChild(), lev);  
  181.         }  
  182.     }  
  183.   
  184.     /** 
  185.      * 中序遍历 
  186.      *  
  187.      * @param node 
  188.      * @param level 
  189.      */  
  190.     private void inorder_traversal(Node node, int level) {// 中序遍历  
  191.         int lev = level + 1;  
  192.         if (node.getLeftChild() != null) {  
  193.             inorder_traversal(node.getLeftChild(), lev);  
  194.         }  
  195.         for (int i = 0; i < level; i++) {  
  196.             System.out.print("-");  
  197.         }  
  198.         System.out.println(node.getIndex());  
  199.         if (node.getRightChild() != null) {  
  200.             inorder_traversal(node.getRightChild(), lev);  
  201.         }  
  202.     }  
  203.   
  204.     /** 
  205.      * 后序遍历 
  206.      *  
  207.      * @param node 
  208.      * @param level 
  209.      */  
  210.     private void postorder_traversal(Node node, int level) {// 后序遍历  
  211.         int lev = level + 1;  
  212.         if (node.getLeftChild() != null) {  
  213.             postorder_traversal(node.getLeftChild(), lev);  
  214.         }  
  215.         if (node.getRightChild() != null) {  
  216.             postorder_traversal(node.getRightChild(), lev);  
  217.         }  
  218.         for (int i = 0; i < level; i++) {  
  219.             System.out.print("-");  
  220.         }  
  221.         System.out.println(node.getIndex());  
  222.     }  
  223.   
  224. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值