文章目录
Binary Search Tree (BST)addremove直接删除删除节点 – 度为1的节点删除节点 – 度为2的节点
code
Binary Search Tree (BST)
任意一个节点的值都大于其左子树所有节点的值任意一个节点的值都小于其右子树所有节点的值它的左右子树也是一棵二叉搜索树二叉搜索树可以大大提高搜索数据的效率二叉搜索树存储的元素必须具备可比较性
add
◼ 添加步骤 找到父节点 parent 创建新节点 node parent.left = node 或者 parent.right = node ◼ 遇到值相等的元素该如何处理? 建议覆盖旧的值
remove
直接删除
node == node.parent.left ✓ node.parent.left = null
node == node.parent.right ✓ node.parent.right = null
node.parent == null ✓ root = null
删除节点 – 度为1的节点
◼ 用子节点替代原节点的位置 child 是 node.left 或者 child 是 node.right 用 child 替代 node 的位置 ✓ 如果 node 是左子节点 ➢ child.parent = node.parent ➢ node.parent.left = child ✓ 如果 node 是右子节点 ➢ child.parent = node.parent ➢ node.parent.right = child ✓ 如果 node 是根节点 ➢ root = child ➢ child.parent = null
删除节点 – 度为2的节点
◼ 先用前驱或者后继节点的值覆盖原节点的值 ◼ 然后删除相应的前驱或者后继节点 ◼ 如果一个节点的度为 2,那么 它的前驱、后继节点的度只可能是 1 和 0
code
public class BinarySearchTree<E>{
private int size
;
private Node
<E> root
;
private Comparator
<E> comparator
;
public BinarySearchTree() {
this(null
);
}
public BinarySearchTree(Comparator
<E> comparator
) {
this.comparator
= comparator
;
}
public int size() {
return size
;
}
public boolean isEmpty() {
return size
== 0;
}
public void clear() {
root
= null
;
size
= 0;
}
public void add(E element
) {
elementNotNullCheck(element
);
if (root
== null
) {
root
= new Node<>(element
, null
);
size
++;
return;
}
Node
<E> parent
= root
;
Node
<E> node
= root
;
int cmp
= 0;
do {
cmp
= compare(element
, node
.element
);
parent
= node
;
if (cmp
> 0) {
node
= node
.right
;
} else if (cmp
< 0) {
node
= node
.left
;
} else {
node
.element
= element
;
return;
}
} while (node
!= null
);
Node
<E> newNode
= new Node<>(element
, parent
);
if (cmp
> 0) {
parent
.right
= newNode
;
} else {
parent
.left
= newNode
;
}
size
++;
}
public void remove(E element
) {
remove(node(element
));
}
public boolean contains(E element
) {
return node(element
) != null
;
}
private void remove(Node
<E> node
) {
if (node
== null
) return;
size
--;
if (node
.hasTwoChildren()) {
Node
<E> s
= successor(node
);
node
.element
= s
.element
;
node
= s
;
}
Node
<E> replacement
= node
.left
!= null
? node
.left
: node
.right
;
if (replacement
!= null
) {
replacement
.parent
= node
.parent
;
if (node
.parent
== null
) {
root
= replacement
;
} else if (node
== node
.parent
.left
) {
node
.parent
.left
= replacement
;
} else {
node
.parent
.right
= replacement
;
}
} else if (node
.parent
== null
) {
root
= null
;
} else {
if (node
== node
.parent
.left
) {
node
.parent
.left
= null
;
} else {
node
.parent
.right
= null
;
}
}
}
private Node
<E> node(E element
) {
Node
<E> node
= root
;
while (node
!= null
) {
int cmp
= compare(element
, node
.element
);
if (cmp
== 0) return node
;
if (cmp
> 0) {
node
= node
.right
;
} else {
node
= node
.left
;
}
}
return null
;
}
@Override
public String
toString() {
StringBuilder sb
= new StringBuilder();
toString(root
, sb
, "");
return sb
.toString();
}
private void toString(Node
<E> node
, StringBuilder sb
, String prefix
) {
if (node
== null
) return;
sb
.append(prefix
).append(node
.element
).append("\n");
toString(node
.left
, sb
, prefix
+ "L---");
toString(node
.right
, sb
, prefix
+ "R---");
}
private int compare(E e1
, E e2
) {
if (comparator
!= null
) {
return comparator
.compare(e1
, e2
);
}
return ((Comparable
<E>)e1
).compareTo(e2
);
}
private void elementNotNullCheck(E element
) {
if (element
== null
) {
throw new IllegalArgumentException("element must not be null");
}
}
private Node
<E> predecessor(Node
<E> node
) {
if (node
== null
) return null
;
Node
<E> p
= node
.left
;
if (p
!= null
) {
while (p
.right
!= null
) {
p
= p
.right
;
}
return p
;
}
while (node
.parent
!= null
&& node
== node
.parent
.left
) {
node
= node
.parent
;
}
return node
.parent
;
}
private Node
<E> successor(Node
<E> node
) {
if (node
== null
) return null
;
Node
<E> p
= node
.right
;
if (p
!= null
) {
while (p
.left
!= null
) {
p
= p
.left
;
}
return p
;
}
while (node
.parent
!= null
&& node
== node
.parent
.right
) {
node
= node
.parent
;
}
return node
.parent
;
}
public static abstract class Visitor<E> {
boolean stop
;
public abstract boolean visit(E element
);
}
private static class Node<E> {
E element
;
Node
<E> left
;
Node
<E> right
;
Node
<E> parent
;
public Node(E element
, Node
<E> parent
) {
this.element
= element
;
this.parent
= parent
;
}
public boolean isLeaf() {
return left
== null
&& right
== null
;
}
public boolean hasTwoChildren() {
return left
!= null
&& right
!= null
;
}
}
}
Reference:小码哥MJ