查询二叉树的兑现
查询二叉树的实现
MainClass ,调试的主类:
首先是Node 类的定义
package SearchTree; public class Node { private Node left; private Node right; private Node Parrent; int data; public Node(Node left, Node right, Node parrent, int data) { super(); this.left = left; this.right = right; Parrent = parrent; this.data = data; } public void setLeft(Node left) { this.left = left; } public void setRight(Node right) { this.right = right; } public void setParrent(Node parrent) { Parrent = parrent; } public void setData(int data) { this.data = data; } public Node getLeft() { return left; } public Node getRight() { return right; } public Node getParrent() { return Parrent; } public int getData() { return data; } }
接着是,Tree 类的定义(各种常用的操作)
package SearchTree; public class Tree { private Node boot=null; // 二叉查找树的根节点 public Node getBoot() { return boot; } public void setBoot(Node boot) { this.boot = boot; } public void Tree_Insert(Node i_node) // 在树中插入一个节点 i_node { Node y = null; Node x = boot; while(x!=null) { y = x; if(i_node.getData() < x.getData()) x = x.getLeft(); else x = x.getRight(); } i_node.setParrent(y); // 设置插入节点的 父节点 if(y == null) // This Tree is empty; { boot = i_node; } else if(y.getData() > i_node.getData()) y.setLeft(i_node); else y.setRight(i_node); } public void InOrder_Tree_Walk() // 中序遍历输出树 { Traversal(boot); } private void Traversal(Node x) { if(x!=null) { Traversal(x.getLeft()); System.out.println(x.getData()); Traversal(x.getRight()); } } public Node Tree_Search(int data) { // Node find =RecursionSearch(boot, data); // 递归的查找 Node find = Non_RecursionSearch(boot, data); // 非递归的查找 if(find == null) System.out.println("Warning:The element that you are searching is not in the tree!"); else System.out.println("find the element in the tree!"); return find; } private Node RecursionSearch(Node b,int data) { if(b==null || b.getData()==data) // | 和 || 两者之间什么关系 ? return b; if(b.getData() < data) return RecursionSearch(b.getRight(), data); else return RecursionSearch(b.getLeft(), data); } private Node Non_RecursionSearch(Node b,int data) // 非递归的查找的实现 { while(b!=null && b.getData()!=data) { if(b.getData() > data) b = b.getLeft(); else b = b.getRight(); } return b; } /*** * 返回树中最小的元素 ,如果树为空的话,返回空的引用 * @return */ public Node Tree_Minmum() { if(boot==null) return null; Node find = minmum(boot); return find; } private Node minmum(Node x) { while(x.getLeft()!=null) x= x.getLeft(); return x; } /** * 返回树中最大的元素,如果树为空的话,返回空的引用 * @return */ public Node Tree_Maximum() { if(boot == null) return boot; Node find = Maximum(boot); return find; } private Node Maximum(Node x) { while(x.getRight()!=null) x = x.getRight(); return x; } /** * 查找一个给定元素data的后继(如果该元素存在的话) * 存在两种情景:1:存在右孩子,则求右孩子的minmum即可 * 2: 不存在右孩子,那么向上循环查找一个父节点,它的左孩子等于循环中的x,此时该点为其后继 * @param data * @return * while 循环是本函数的核心代码(难点) */ public Node Tree_Successor(int data) { Node x= Tree_Search(data); // 获得元素data 的节点引用。 if(x==null) return null; if(x.getRight()!=null) return minmum(x.getRight()); Node y = x.getParrent(); while(y!=null && x==y.getRight()) { x=y; y= y.getParrent(); } return y; } /** * Funtion:查找一个给定元素的中序遍历的前驱节点,有两种情况: * 1:该节点存在左孩子,那么求左孩子的Maximum * 2:该节点没有左孩子,那么向上递归求(通过循环)一个存在右孩子的节点,即为所求节点的前驱节点 * @param data * @return */ public Node Tree_Predecessor(int data) { Node x = Tree_Search(data); // 获得元素data 的引用 if(x==null) return null; if(x.getLeft()!=null) // 第一种情况,存在左孩子 return Maximum(x.getLeft()); Node y = x.getParrent(); while(y!=null && y.getLeft()==x) { x=y; y= y.getParrent(); } return y; } /** * funtion:删除树中的元素data(如果存在的话),删除时存在三种情况: * 1:该节点没有孩子节点,则,直接删除 * 2:该节点有一个孩子节点,那么删除节点之后,将该节点的父节点执行该节点的子节点 * 3:存在两个子节点,那么将该节点的后继,覆盖带该节点即可,后继节点一定不会有两个子节点 * @param data */ public void Tree_Delete(int data) { Node z = Tree_Search(data); Node x,y; if(z==null)return; // 不存在元素data if((z.getLeft()==null)||(z.getRight()==null)) //如果是前两种情况 { y = z; } else y = Tree_Successor(data);// 第三种情况 if(y.getLeft()!=null) // 获得要删除节点的子节点 x = y.getLeft(); else x = y.getRight(); if(x!=null) x.setParrent(y.getParrent()); if(y.getParrent()==null) boot = x; else if(y==y.getParrent().getLeft()) y.getParrent().setLeft(x); else y.getParrent().setRight(x); if(y!=z) //删除节点不是指定节点,那么是第三种情况 { z.setData(y.getData()); //修改删除节点的data 域为它的后继节点的data域 ,相对于写该引用简单很多 } } }
MainClass ,调试的主类:
package SearchTree; public class MainClass { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Tree T =new Tree(); int[] a = {4 ,3 ,5,2,6,7,1}; for(int i=0;i < a.length; i++) { T.Tree_Insert(new Node(null, null, null, a[i])); } T.InOrder_Tree_Walk(); System.out.println("The minmum element is :" +T.Tree_Minmum().getData()); System.out.println("The Maximum element is :" + T.Tree_Maximum().getData()); System.out.println("The element 6's successor is:" + T.Tree_Successor(6).getData()); System.out.println("The element 6's predecessor is:" + T.Tree_Predecessor(6).getData()); T.Tree_Delete(5); T.InOrder_Tree_Walk(); } }