package Alg; public class BSTree { private BSTreeNode root = null; //树根节点 private int count = 0; //树的节点数 public int getCount() { return count; } public enum MatchType {E, GE, LE}; /** * 根据值进行搜索 * @param val 匹配值 * @param matchType 匹配方式 E为严格相等匹配,GE为大于等于匹配,LE为小于等于匹配 * @return 匹配模式为E时,如果没有找到匹配项,返回null,否则返回匹配到的节点 * 匹配模式为GE时,如果匹配到数据,返回匹配到的数据,否则返回大于该数据的最小节点 * 匹配模式为LE时,如果匹配到数据,返回匹配到的数据,否则返回小于该数据的最大节点 */ public BSTreeNode search(int val, MatchType matchType) { BSTreeNode n = search(val); if (n == null) return null; if (n.getValue() == val) return n; switch (matchType) { case LE: if (n.getValue() < val) return n; return getLittleSmaller(n); case GE: if (n.getValue() > val) return n; return getLittleBigger(n); default: } return null; } private BSTreeNode search(int val) { if (root == null) return null; return search(root, val); } /** * 获取距离该值最近的节点 * @param n * @param val * @return */ private BSTreeNode search(BSTreeNode n, int val) { int v = n.getValue(); if (v == val) return n; else if (v > val) { if (n.getLeftChild() == null) return n; return search(n.getLeftChild(), val); } if (n.getRightChild() == null) return n; return search(n.getRightChild(), val); } /** * 进行插入操作 * @param val */ public void insert(int val) { if (root == null) { root = BSTreeNode.createNode(val); count++; return; } BSTreeNode x = search(val); if (x.getValue() == val) return; BSTreeNode n = BSTreeNode.createNode(val); count++; if (x.getValue() < val) x.setRightChild(n); else x.setLeftChild(n); n.setParent(x); } /** * 删除值 * @param val */ public void delete(int val) { if (root == null) return; BSTreeNode x = search(val); if (x.getValue() != val) return; count--; //删除仅剩的一个节点 if (count == 0) { root = null; return; } //当为叶子节点时从父节点将该节点的连接删除 if (x.isLeaf()) { BSTreeNode p = x.getParent(); if (p.getLeftChild() == x) p.setLeftChild(null); else p.setRightChild(null); } BSTreeNode lc = x.getLeftChild(); BSTreeNode rc = x.getRightChild(); //如果具有两个非空子树,或者从左子树中取得最大的节点代替当前节点 //或者从右子树取得最小节点代替当前节点 //然后删除代替的节点 if (lc != null && rc != null) { BSTreeNode lrm = getRightMostNode(lc); BSTreeNode rlm = getLeftMostNode(rc); //如果是叶节点则可以简单替换节点进行处理,否则要替换后进行再次替换 if (lrm.isLeaf()) { x.setValue(lrm.getValue()); BSTreeNode rp = lrm.getParent(); rp.setRightChild(null); return ; } else if (rlm.isLeaf()) { x.setValue(rlm.getValue());; BSTreeNode lp = rlm.getParent(); lp.setLeftChild(null); return ; } else { //调换两个节点,并将删除转换为只有一个子树的情况 x.setValue(lrm.getValue()); x = lrm; } } //如果只有一个子树(左子树或右子树),则用子树中的根代替当前节点 BSTreeNode p = x.getParent(); lc = x.getLeftChild(); rc = x.getRightChild(); if (lc != null) { if (p.getLeftChild() == x) p.setLeftChild(lc); else p.setRightChild(lc); return ; } if (rc != null) { if (p.getLeftChild() == x) p.setLeftChild(rc); else p.setRightChild(rc); } } /** * 以升序方式打印树中节点,实际就是中根的树的访问次序 */ public void printInAscOrd() { if (root == null) System.out.println("没有数据"); printInOrder(root); } /** * 将二叉树转换为升序排列的数组 * @return 返回升序排序后的数组 */ public BSTreeNode[] getAscOrderArray() { BSTreeNode[] ary = new BSTreeNode[count]; int pos = fillArrayInOrd(ary, 0, root); if (pos != count) System.out.println("构造数组出错"); return ary; } private int fillArrayInOrd(BSTreeNode[] ary, int pos, BSTreeNode root) { int npos = pos; if (root.getLeftChild() != null) { npos = fillArrayInOrd(ary, npos, root.getLeftChild()); } ary[npos] = root; npos++; if (root.getRightChild() != null) { npos = fillArrayInOrd(ary, npos, root.getRightChild()); } return npos; } /** * 获取大于当前节点的最小节点 * @param x * @return 如果没有大于该节点的节点,则返回null */ private BSTreeNode getLittleBigger(BSTreeNode x) { BSTreeNode rc = x.getRightChild(); if (rc != null) { return getLeftMostNode(rc); } else { //回溯祖先节点,取得第一个令该节点为左子树节点的祖先节点 BSTreeNode p = x.getParent(); BSTreeNode s = x; while (p != null) { if (p.getLeftChild() == s) break; s = p; p = p.getParent(); } return p; } } private BSTreeNode getLittleSmaller(BSTreeNode x) { BSTreeNode lc = x.getLeftChild(); if (lc != null) { return getRightMostNode(lc); } else { //回溯祖先节点,取得第一个令该节点为左子树节点的祖先节点 BSTreeNode p = x.getParent(); BSTreeNode s = x; while (p != null) { if (p.getRightChild() == s) break; s = p; p = p.getParent(); } if (p != null) return p; } return null; } private BSTreeNode getLeftMostNode(BSTreeNode x) { BSTreeNode l = x; while (l.getLeftChild() != null) { l = l.getLeftChild(); } return l; } private BSTreeNode getRightMostNode(BSTreeNode x) { BSTreeNode r = x; while (r.getRightChild() != null) { r = r.getRightChild(); } return r; } private void printInOrder(BSTreeNode n) { if (n.getLeftChild() != null) printInOrder(n.getLeftChild()); printNode(n); if (n.getRightChild() != null) printInOrder(n.getRightChild()); } private void printNode(BSTreeNode n) { System.out.print("[" + n.getValue() + "]"); } private void checkTreeValidation() throws Exception { BSTreeNode[] ary = this.getAscOrderArray(); for (int i = 0; i < ary.length - 1; i++) { if (ary[i].getValue() > ary[i + 1].getValue()) { throw new Exception("二叉树出现错误"); } } } public static BSTree buildRandomTree1() { BSTree tree = new BSTree(); try { tree.insert(8569); tree.insert(7556); tree.insert(3421); tree.insert(5665); tree.insert(5169); tree.insert(9189); tree.insert(5656); tree.insert(6691); tree.insert(6932); tree.insert(3511); tree.insert(4269); tree.insert(3556); tree.checkTreeValidation(); return tree; } catch (Exception e) { e.printStackTrace(); return null; } } public static BSTree buildRandomTree2() { BSTree tree = new BSTree(); try { tree.insert(53); tree.insert(12); tree.insert(27); tree.insert(99); tree.insert(46); tree.insert(5); tree.insert(38); tree.checkTreeValidation(); return tree; } catch (Exception e) { e.printStackTrace(); return null; } } public static void testInsertCase1() { BSTree tree = buildRandomTree1(); if (tree == null) System.out.println("构造二叉树出错"); tree.printInAscOrd(); } public static void testInsertCase2() { BSTree tree = buildRandomTree2(); if (tree == null) System.out.println("构造二叉树出错"); tree.printInAscOrd(); } public static void testGetArray() { BSTree tree = buildRandomTree2(); if (tree == null) System.out.println("构造二叉树出错"); BSTreeNode[] ary = tree.getAscOrderArray(); for (int i = 0; i < ary.length; i++) { System.out.print("["); System.out.print(ary[i].getValue()); System.out.print("]"); } } public static void testDeleteCase1() { BSTree tree = buildRandomTree2(); if (tree == null) System.out.println("构造二叉树出错"); tree.printInAscOrd(); BSTreeNode[] ary = tree.getAscOrderArray(); System.out.println(); System.out.println("删除" + ary[3].getValue()); tree.delete(ary[3].getValue()); tree.printInAscOrd(); System.out.println(); System.out.println("删除" + ary[5].getValue()); tree.delete(ary[5].getValue()); tree.printInAscOrd(); } public static void testGetLittleBigger(){ BSTree tree = buildRandomTree2(); if (tree == null) System.out.println("构造二叉树出错"); tree.printInAscOrd(); System.out.println(""); BSTreeNode[] ary = tree.getAscOrderArray(); for (int i = 0; i < ary.length - 1; i++) { BSTreeNode n = ary[i]; BSTreeNode b = tree.getLittleBigger(n); System.out.println("当前数值" + n.getValue() +"." + "较大数值为" + b.getValue()); if (b.getValue() != ary[i + 1].getValue()) System.out.println("出现错误"); else System.out.println("正确"); } } public static void testGetLittleSmaller() { BSTree tree = buildRandomTree2(); if (tree == null) System.out.println("构造二叉树出错"); tree.printInAscOrd(); System.out.println(""); BSTreeNode[] ary = tree.getAscOrderArray(); for (int i = ary.length - 1; i > 0; i--) { BSTreeNode n = ary[i]; BSTreeNode s = tree.getLittleSmaller(n); System.out.println("当前数值" + n.getValue() +"." + "较小数值为" + s.getValue()); if (s.getValue() != ary[i - 1].getValue()) System.out.println("出现错误"); else System.out.println("正确"); } } }
package Alg; public class BSTreeNode { private BSTreeNode leftChild = null; private BSTreeNode rightChild = null; private BSTreeNode parent = null; private int value = Integer.MIN_VALUE; public static BSTreeNode createNode(int val) { return new BSTreeNode(val); } private BSTreeNode(int val) { leftChild = null; rightChild = null; parent = null; value = val; } public boolean isLeaf() { if (getLeftChild() == null && getRightChild() == null) return true; return false; } public boolean isRoot() { if (getParent() == null) return true; return false; } public BSTreeNode getLeftChild() { return leftChild; } public void setLeftChild(BSTreeNode leftChild) { this.leftChild = leftChild; } public BSTreeNode getRightChild() { return rightChild; } public void setRightChild(BSTreeNode rightChild) { this.rightChild = rightChild; } public BSTreeNode getParent() { return parent; } public void setParent(BSTreeNode parent) { this.parent = parent; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
写在纸上的内容