public class BinarySortTree { public static class Node{ Float data = null; Node leftChild; Node rightChild; Node father; } Node root; public Node search(Node root, Node node){ if(node == null){ throw new IllegalArgumentException("node can't ne null , node = "+node); } if(root == null){ return null; } if(root.data > node.data){ return search(root.leftChild,node); } else if(root.data < node.data){ return search(root.rightChild,node); } else{ return root; } } public void addNode(float data) { Node thisNode = new Node(); thisNode.data = data; //根结点是null则说明是空树,直接赋值 if(root == null){ root = thisNode; return; } Node n = root; //数据比结点小则往左子树走,等于或大则往右子树走,结点为null则插入 while (true){ if(n.data > data){ if(n.leftChild == null){ n.leftChild = thisNode; thisNode.father = n; break; } else { n = n.leftChild; } } else { if(n.rightChild == null){ n.rightChild = thisNode; thisNode.father = n; break; } else { n = n.rightChild; } } } } /** * 中序遍历 * @param root */ public void inorder(Node root){ if(root != null){ inorder(root.leftChild); System.out.println(root.data); inorder(root.rightChild); } } /** * 递归找到删除结点 * @param father * @param isLeftChild * @param root * @param node */ public void delete(Node father,boolean isLeftChild,Node root,Node node){ if(root == null){ throw new IllegalArgumentException("there is no such node"); } if(root.data.equals(node.data)){ deleteDetail(father,isLeftChild,root); } else if(root.data > node.data){ delete(root,true,root.leftChild,node); } else{ delete(root,false,root.rightChild,node); } } /** * 找到删除结点后的操作 * @param father * @param isLeftChild * @param root */ private void deleteDetail(Node father,boolean isLeftChild, Node root){ //没有孩子节点 if(root.rightChild == null && root.leftChild == null){ //要删除的结点是根结点 if(root == this.root){ this.root = null; } else { if(isLeftChild){ father.leftChild = null; } else { father.rightChild = null; } } } //只有右孩子节点 else if(root.rightChild != null && root.leftChild == null){ //要删除的结点是根结点 if(root == this.root){ this.root = root.rightChild; } else { if(isLeftChild){ father.leftChild = root.rightChild; } else { father.rightChild = root.rightChild; } } } //只有左孩子节点 else if(root.rightChild == null && root.leftChild != null){ //要删除的结点是根结点 if(root == this.root){ this.root = root.leftChild; } else { if(isLeftChild){ father.leftChild = root.leftChild; } else { father.rightChild = root.leftChild; } } } //有两个孩子节点 else { //待删除结点的中序遍历前驱 Node deletePre = root.leftChild; //待删除结点的中序遍历前驱的父结点 Node deletePreFather = deletePre; //如果待删除结点的中序遍历前驱就是他的左孩子 if(deletePre.rightChild == null){ //要删除的结点是根结点 if(root == this.root){ this.root = deletePre; deletePre.rightChild = root.rightChild; } else { if(isLeftChild){ father.leftChild = deletePre; deletePre.rightChild = root.rightChild; } else { father.rightChild = deletePre; deletePre.rightChild = root.rightChild; } } } else { //寻找删除结点的中序遍历前驱结点 while (deletePre.rightChild != null){ deletePreFather = deletePre; deletePre = deletePre.rightChild; } //如果待删结点前驱有左孩子,则把用户该左孩子顶替该结点 if(deletePre.leftChild != null){ deletePreFather.rightChild = deletePre.leftChild; } //若没有左孩子,则把该结点和父结点的联系取消 else{ deletePreFather.rightChild = null; } //要删除的结点是根结点 if(root == this.root){ this.root = deletePre; } else { //如果删除结点是左孩子,则把左孩子的链接指向 待删结点前驱 if(isLeftChild){ father.leftChild = deletePre; } else { father.rightChild = deletePre; } } //待删结点前驱上位之后,把相应的映射关系串好 deletePre.leftChild = root.leftChild; deletePre.rightChild = root.rightChild; } } }
二叉排序树的增加和查找都是很简单的,对其的中序遍历就是得到排序结果。
删除操作比较复杂,大致分成4种情况
1.删除的结点无孩子结点
2.删除的结点只有左孩子
3.删除的结点只有右孩子
4.删除的结点既有左孩子又有右孩子
当是第4种情况时,可以用删除结点的前驱或者后继来顶替它的位置,代码中使用了前驱结点