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;
}
}
写在纸上的内容