Node类:
// 二叉树节点
public class Node {
// 数据
public Long data;
// 左子节点
public Node leftChild;
// 右子节点
public Node rightChild;
public Node(long data) {
this.data = data;
}
}
二叉树的插入、查找、遍历较为容易,删除节点较为麻烦点。
要删除的节点可分成3种情况去处理: (1) 该节点没有子节点:直接删除该节点即可; (2) 该节点只有一个节点,左子节点或者右子节点:只需将其父节点的左/右子节点的引用指向其子节点即可; (3) 该节点有两个子节点:需要将该节点的右子树中最小的节点替换到该节点即可。
Tree类:
public class Tree {
// 根节点
private Node root;
/**
* 插入节点
* @param value
*/
public void insert(long value) {
// 创建新节点
Node newNode = new Node(value);
Node current = root;
// 如果root为null,则树为空
if(root == null) {
root = newNode;
} else {
while (true) {
// 如果当前节点数据比value要小,则向左;否则向右
if(current.data > value) {
if(current.leftChild == null) {
current.leftChild = newNode;
return;
} else {
current = current.leftChild;
}
} else {
if(current.rightChild == null) {
current.rightChild = newNode;
return;
} else {
current = current.rightChild;
}
}
}
}
}
/**
* 删除节点
* @param value
*/
public boolean delete(long value){
// 当前节点
Node current = root;
// 父节点
Node parent = current;
// 标记要删除的节点,是其父节点的左子节点还是右子节点
boolean isLeftChild = true;
// 查找要删除的节点
while (current.data != value) {
parent = current;
if(current.data > value) {
current = current.leftChild;
isLeftChild = true;
} else if(current.data < value) {
current = current.rightChild;
isLeftChild = false;
}
// 如果查找不到
if(current == null)
return false;
}
/*
要删除的节点有3种情况:
(1) 该节点没有子节点;
(2) 该节点只有一个节点,左子节点或者右子节点;
(3) 该节点有两个子节点。(这种较为复杂)
*/
if(current.leftChild == null && current.rightChild == null) { // 该节点没有子节点;
if(current == root) {
root = null;
}
if(isLeftChild) {
parent.leftChild = null;
} else {
parent.rightChild = null;
}
} else if(current.rightChild == null) { // 该节点只有一个左子节点;
if(current == root) {
root = current.leftChild;
}
if(isLeftChild) {
parent.leftChild = current.leftChild;
} else {
parent.rightChild = current.leftChild;
}
} else if(current.leftChild == null) { // 该节点只有一个右子节点;
if(current == root) {
root = current.rightChild;
}
if(isLeftChild) {
parent.leftChild = current.rightChild;
} else {
parent.rightChild = current.rightChild;
}
} else { // 该节点有两个子节点;
/*
拿到中序后继的节点,也就是当前节点的右子树中数值最小的那个节点,
将该节点替换掉当前要被删除节点的位置上,即可得到树的平衡
*/
Node successor = getSuccessor(current);
if(current == root) {
root = successor;
} else if(isLeftChild) {
parent.leftChild = successor;
} else {
parent.rightChild = successor;
}
successor.leftChild = current.leftChild;
}
return true;
}
// 拿到中序后继的节点,也就是当前节点的右子树中数值最小的那个节点
private Node getSuccessor(Node delNode) {
Node successor = delNode;
Node successorParent = delNode;
Node current = delNode.rightChild;
while(current != null) {
successorParent = successor;
successor = current;
current = current.leftChild;
}
if(successor != delNode.rightChild) {
successorParent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}
/**
* 按照中序遍历打印数
*/
public void list(){
inOrderTraverse(root);
}
private void inOrderTraverse(Node node) {
if (node == null)
return;
inOrderTraverse(node.leftChild);
System.out.print(node.data + " ");
inOrderTraverse(node.rightChild);
}
/**
* 查找节点
* @param value
*/
public Node find(long value){
if(root == null)
return null;
Node current = root;
while (current.data != value) {
// 进行比较,查找值比当前节点小时,继续左边查找;否则右边查找
if(current.data > value) {
current = current.leftChild;
} else {
current = current.rightChild;
}
if(current == null)
return null;
}
return current;
}
}
测试类:
public class Test {
public static void main(String[] args) {
Tree tree = new Tree();
int[] arr = new int[]{5,3,4,1,12,15,9,8,6,7,10,13,14,30};
for (int i = 0; i < arr.length; i++) {
tree.insert(arr[i]);
}
tree.list();
System.out.println();
System.out.println(tree.delete(12));
tree.list();
}
}