在计算机科学中,树是一种非常重要的数据结构,而且有非常广泛的应用,例如linux下的目录结构就可以看成是一棵树,另外树也是存储大量的数据一种解决方法,二叉排序树是树的一种特殊情形,它的每个节点之多只能有两个子节点,同时左子树的节点都小于它的父节点,右子树中的节点都大于它的父节点,二叉排序树在搜索中的应用非常广泛,同时二叉排序树的一个变种(红黑树)是java中TreeMap和TreeSet的实现基础。下边是二叉排序树的定义,其中用到了两个类,一个是Node类,代表树中的节点,另外一个是Name类,表示节点的数据,Name类实现Comparable接口,这样才可以比较节点的大小。
public class BinarySearchTree{ private Node root; private int size; public BinarySearchTree(Node root){ this.root=root; size++; } public int getSize(){ return this.size; } public boolean contains(Name name){ return contains(name,this.root); //return false; } private boolean contains(Name n,Node root){ if(root==null){ return false; } int compare=n.compareTo(root.element); if(compare>0){ if(root.right!=null){ return contains(n,root.right); }else{ return false; } }else if(compare<0){ if(root.left!=null){ return contains(n,root.left); }else{ return false; } }else{ return true; } } public boolean insert(Name n){ boolean flag = insert(n,this.root); if(flag) size++; return flag; } private boolean insert(Name n,Node root){ if(root==null){ this.root=new Node(n); return true; }else if(root.element.compareTo(n)>0){ if(root.left!=null){ return insert(n,root.left); }else{ root.left=new Node(n); return true; } }else if(root.element.compareTo(n)<0){ if(root.right!=null){ return insert(n,root.right); }else{ root.right=new Node(n); return true; } }else{ root.frequency++; return true; } } public boolean remove(Name name){ root = remove(name,this.root); if(root != null){ size--; return true; } return false; } private Node remove(Name name,Node root){ int compare = root.element.compareTo(name); if(compare == 0){ if(root.frequency>1){ root.frequency--; }else{ /**根据删除节点的类型,分成以下几种情况 **①如果被删除的节点是叶子节点,直接删除 **②如果被删除的节点含有一个子节点,让指向该节点的指针指向他的儿子节点 **③如果被删除的节点含有两个子节点,找到左字数的最大节点,并替换该节点 **/ if(root.left == null && root.right == null){ root = null; }else if(root.left !=null && root.right == null){ root = root.left; }else if(root.left == null && root.right != null){ root = root.right; }else{ //被删除的节点含有两个子节点 Node newRoot = root.left; while (newRoot.left != null){ newRoot = newRoot.left;//找到左子树的最大节点 } root.element = newRoot.element; root.left = remove(root.element,root.left); } } }else if(compare > 0){ if(root.left != null){ root.left = remove(name,root.left); }else{ return null; } }else{ if(root.right != null){ root.right = remove(name,root.right); }else{ return null; } } return root; } public String toString(){ //中序遍历就可以输出树中节点的顺序 return toString(root); } private String toString(Node n){ String result = ""; if(n != null){ if(n.left != null){ result += toString(n.left); } result += n.element + " "; if(n.right != null){ result += toString(n.right); } } return result; } }
在二叉排序树的操作中,节点的删除时最难处理的,要分成很多种情况分别进行处理,下边是Node类和Name类的定义:
class Node{ public Name element; public Node left; public Node right; public int frequency = 1; public Node(Name n){ this.element=n; } } class Name implements Comparable<Name>{ private String firstName; private String lastName; public Name(String firstName,String lastName){ this.firstName=firstName; this.lastName=lastName; } public int compareTo(Name n) { int result = this.firstName.compareTo(n.firstName); return result==0?this.lastName.compareTo(n.lastName):result; } public String toString(){ return firstName + "-" +lastName; } }
最后是二叉排序树的测试:
public static void main(String[] args){ //System.out.println("sunzhenxing"); Node root = new Node(new Name("sun","zhenxing5")); BinarySearchTree bst =new BinarySearchTree(root); bst.insert(new Name("sun","zhenxing3")); bst.insert(new Name("sun","zhenxing7")); bst.insert(new Name("sun","zhenxing2")); bst.insert(new Name("sun","zhenxing4")); bst.insert(new Name("sun","zhenxing6")); bst.insert(new Name("sun","zhenxing8")); System.out.println(bst); bst.remove(new Name("sun","zhenxing2")); System.out.println(bst); bst.remove(new Name("sun","zhenxing7")); System.out.println(bst); }
测试输出是:
sun-zhenxing2 sun-zhenxing3 sun-zhenxing4 sun-zhenxing5 sun-zhenxing6 sun-zhenxing7 sun-zhenxing8
sun-zhenxing3 sun-zhenxing4 sun-zhenxing5 sun-zhenxing6 sun-zhenxing7 sun-zhenxing8
sun-zhenxing3 sun-zhenxing4 sun-zhenxing5 sun-zhenxing6 sun-zhenxing8