排序二叉树是一种特殊结构的二叉树,通过它可以非常方便地对树中所有节点进行排序和检索。
特点:
1、若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值。
2、若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值。
3、它的左、右子树分别为排序二叉树。
代码:结合JVM内存分配图。
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
public class SortedBinTree<T extends Comparable> {
static class Node {
Object data;
Node parent;
Node left;
Node right;
public Node(Object data, Node parent, Node left, Node right) {
this.data = data;
this.parent = parent;
this.left = left;
this.right = right;
}
public String toString() {
return "[data=" + data + "]";
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj.getClass() == Node.class) {
Node target = (Node) obj;
return data.equals(target.data)
&& left == target.left
&& right == target.right
&& parent == target.parent;
}
return false;
}
}
private Node root;
public SortedBinTree() {
root = null;
}
public SortedBinTree(T o) {
root = new Node(0, null, null, null);
}
/**
* 从根节点开始检索,设置 current指向根节点,设置parent也指向根节点,
* 将插入值与current指向的节点进行比较,如果大于0,则将current指向下一个右节点,否则指向下一个左节点。
* 每次current下移一个节点,parent都指向下移的这个节点,当current为null时,parent继续指向最后获取的那个节点,
* 此时需要在parent指向的节点下面添加新节点,如果获取的比较值大于0,添加右节点,否则添加左节点。
*
* @param ele
*/
public void add(T ele) {
if (root == null) {
root = new Node(ele, null, null, null);
} else {
Node current = root;
Node parent = null;
int cmp = 0;
do {
parent = current;
cmp = ele.compareTo(current.data);
if (cmp > 0) {
current = current.right;
} else {
current = current.left;
}
} while (current != null);
Node newNode = new Node(ele, parent, null, null);
if (cmp > 0) {
parent.right = newNode;
} else {
parent.left = newNode;
}
}
}
public void remove(T ele) {
//获取要删除的节点
Node target = getNode(ele);
if (target == null) {
return;
}
/**
*如果当前节点的左右节点都为空:1:根节点,2:叶子节点
* 结合JVM分配内存图去体会,引用变量指向,你指我 ,我指你!!!
*/
if (target.left == null && target.right == null) {
//如果是根节点,直接释放指针
if (target == root) {
root = null;
} else {
//如果删除的节点的是其父节点的左子节点,则将其父节点的左子节点指针释放,并且将其指向父节点的指针释放
if (target == target.parent.left) {
target.parent.left = null;
} else {
//如果删除的节点的是其父节点的右子节点,则将其父节点的右子节点指针释放,并且将其指向父节点的指针释放
target.parent.right = null;
}
target.parent = null;
}
} else if (target.left == null && target.right != null) {
//如果是根节点,则设置当前节点的右节点为根节点
if (target == root) {
root = target.right;
} else {
//如果要删除的节点的是其父节点的左子节点,则将当前节点父节点左子节点指针指向其右节点
if (target == target.parent.left) {
target.parent.left = target.right;
} else {
target.parent.right = target.right;
}
target.right.parent = target.parent;
}
} else if (target.left != null && target.right == null) {
if (target == root) {
root = target.left;
} else {
if (target == target.parent.left) {
target.parent.left = target.left;
} else {
target.parent.right = target.left;
}
target.left.parent = target.parent;
}
} else {
Node leftMaxNode = target.left;
while (leftMaxNode.right != null) {
leftMaxNode = leftMaxNode.right;
}
leftMaxNode.parent.right = null;
leftMaxNode.parent = target.parent;
if (target == target.parent.left) {
target.parent.left = leftMaxNode;
} else {
target.parent.right = leftMaxNode;
}
leftMaxNode.left = target.left;
leftMaxNode.right = target.right;
target.parent = target.left = target.right = null;
}
}
public Node getNode(T ele) {
Node p = root;
while (p != null) {
int cmp = ele.compareTo(p.data);
if (cmp < 0) {
p = p.left;
} else if (cmp > 0) {
p = p.right;
} else {
return p;
}
}
return null;
}
public List<Node> breadthFirst() {
Queue<Node> queue = new ArrayDeque<>();
List<Node> list = new ArrayList<>();
if (root != null) {
queue.offer(root);
}
while (!queue.isEmpty()) {
list.add(queue.peek());
Node p = queue.poll();
if (p.left != null) {
queue.offer(p.left);
}
if (p.right != null) {
queue.offer(p.right);
}
}
return list;
}
public static void main(String[] args) {
SortedBinTree<Integer> tree = new SortedBinTree<>();
tree.add(5);
tree.add(20);
tree.add(10);
tree.add(3);
tree.add(8);
tree.add(15);
tree.add(30);
System.out.println(tree.breadthFirst());
tree.remove(20);
System.out.println(tree.breadthFirst());
}
}