二叉搜索树的中序遍历
中序遍历时不打印, 直接尾插到链表里面.
// 1. 遍历二叉搜索树
public void inOrder(TreeNode left) {
if (this.root == null) {
return;
}
inOrder(root.left);
add(root);
inOrder(root.right);
}
public void add(TreeNode node) {
if (tail == null) {
head = tail = node;
} else {
tail.right = node;
node.left = tail;
tail = tail.right;
}
}
二叉搜索树的增加
先找到需要插入的位置, 然后进行插入
// 2. 二叉搜索树的插入
public TreeNode insert(char val) {
if (root == null) {
root = new TreeNode(val);
return root;
}
TreeNode cur = root;
TreeNode pre = null;
int cmp = 0;
while (cur != null) {
cmp = compare(val, cur.val);
if (cmp < 0) {
pre = cur;
cur = cur.left;
} else if (cmp > 0) {
pre = cur;
cur = cur.right;
} else {
// 插入失败
return root;
}
}
if (cmp < 0) {
pre.left = new TreeNode(val);
} else {
pre.right = new TreeNode(val);
}
return root;
}
二叉搜索树的删除
先找到要删除的结点, 然后借助 removeInternal 函数进行删除
// 3. 二叉搜索树的删除
public boolean remove(char c) {
// 先找到该节点
TreeNode cur = root;
TreeNode pre = null;
while (cur != null) {
int cmp = compare(c, cur.val);
if (cmp == 0) {
removeInternal(cur, pre);
return true;
} else if (cmp < 0) {
pre = cur;
cur = cur.left;
} else {
pre = cur;
cur = cur.right;
}
}
return false;
}
删除 node 节点时, 分为四种情况(pre 是要删除结点的父节点)
<1>要删除的结点没有左子树和右子树
①要删除的结点为根节点
if (node == root) {
root = null;
}
②要删除的结点不为根节点
// 如果父节点的左孩子是要删除的结点 node
if (node == pre.left) {
pre.left = null;
} else {
// 如果父节点的右孩子是要删除的结点 node
pre.right = null;
}
<2>要删除的结点有左子树和无右子树
①要删除的结点为根节点
if (node == root) {
root = root.left;
}
②要删除的结点不为根节点
// 如果父节点的左孩子是要删除的结点 node
if (node == pre.left) {
pre.left = node.left;
} else {
// 如果父节点的右孩子是要删除的结点 node
pre.right = node.left;
}
<3>要删除的结点没有左子树和有右子树
①要删除的结点为根节点
if (node == root) {
root = root.right;
}
②要删除的结点不为根节点
// 如果父节点的左孩子是要删除的结点 node
if (node == pre.left) {
pre.left = node.right;
} else {
// 如果父节点的右孩子是要删除的结点 node
pre.right = node.right;
}
<4>要删除的结点有左子树和右子树
找左子树中最大的结点(左子树中最右边的结点), 将该节点与要删除结点进行替换, 然后删除该节点(左子树中最右边的结点).
private void removeInternal(TreeNode node, TreeNode pre) {
if (node.left == null && node.right == null) {
if (node == root) {
root = null;
} else if (node == pre.left) {
pre.left = null;
} else {
pre.right = null;
}
} else if (node.left != null && node.right == null) {
if (node == root) {
root = root.left;
} else if (node == pre.left) {
pre.left = node.left;
} else {
pre.right = node.left;
}
} else if (node.left == null && node.right != null) {
if (node == root) {
root = node.right;
} else if (node == pre.left) {
pre.left = node.right;
} else {
pre.right = node.right;
}
} else {
// 找左子树中最大的与要删除的结点的值进行替换
TreeNode parent = node;
TreeNode child = node.left;
// 一直往右走找值最大的结点 child
while (child.right != null) {
parent = child;
child = child.right;
}
// 进行替换
node.val = child.val;
// 删除被替换的结点
// 如果要删除结点的左子树没有右节点
if (parent == node) {
parent.left = child.left;
} else {
// 如果要删除结点的左子树有右节点
parent.right = child.left;
}
}
}
二叉搜索树的查找
// 4. 查找
public TreeNode find(TreeNode root, char c) {
TreeNode cur = root;
int cmp = 0;
while (cur != null) {
cmp = compare(c, cur.val);
if (cmp < 0) {
cur = cur.left;
} else if (cmp > 0) {
cur = cur.right;
} else {
return cur;
}
}
return null;
}
完整代码
public class BST {
TreeNode root = null;
TreeNode head = null;
TreeNode tail = null;
// 二叉搜索树的中序遍历是有序的
// 1. 遍历二叉搜索树
public void inOrder(TreeNode left) {
if (this.root == null) {
return;
}
inOrder(root.left);
add(root);
inOrder(root.right);
}
public void add(TreeNode node) {
if (tail == null) {
head = tail = node;
} else {
tail.right = node;
node.left = tail;
tail = tail.right;
}
}
// 2. 二叉搜索树的插入
public TreeNode insert(char val) {
if (root == null) {
root = new TreeNode(val);
return root;
}
TreeNode cur = root;
TreeNode pre = null;
int cmp = 0;
while (cur != null) {
cmp = compare(val, cur.val);
if (cmp < 0) {
pre = cur;
cur = cur.left;
} else if (cmp > 0) {
pre = cur;
cur = cur.right;
} else {
// 插入失败
return root;
}
}
if (cmp < 0) {
pre.left = new TreeNode(val);
} else {
pre.right = new TreeNode(val);
}
return root;
}
private int compare(char val, char val1) {
return val - val1;
}
// 3. 二叉搜索树的删除
public boolean remove(char c) {
// 先找到该节点
TreeNode cur = root;
TreeNode pre = null;
while (cur != null) {
int cmp = compare(c, cur.val);
if (cmp == 0) {
removeInternal(cur, pre);
return true;
} else if (cmp < 0) {
pre = cur;
cur = cur.left;
} else {
pre = cur;
cur = cur.right;
}
}
return false;
}
private void removeInternal(TreeNode node, TreeNode pre) {
if (node.left == null && node.right == null) {
if (node == root) {
root = null;
} else if (node == pre.left) {
pre.left = null;
} else {
pre.right = null;
}
} else if (node.left != null && node.right == null) {
if (node == root) {
root = root.left;
} else if (node == pre.left) {
pre.left = node.left;
} else {
pre.right = node.left;
}
} else if (node.left == null && node.right != null) {
if (node == root) {
root = node.right;
} else if (node == pre.left) {
pre.left = node.right;
} else {
pre.right = node.right;
}
} else {
// 找左子树中最大的与要删除的结点的值进行替换
TreeNode parent = node;
TreeNode child = node.left;
// 一直往右走找最大的
while (child.right != null) {
parent = child;
child = child.right;
}
// 进行替换
node.val = child.val;
// 删除被替换的结点
if (parent == node) {
parent.left = child.left;
} else {
parent.right = child.left;
}
}
}
// 4. 查找
public TreeNode find(TreeNode root, char c) {
TreeNode cur = root;
int cmp = 0;
while (cur != null) {
cmp = compare(c, cur.val);
if (cmp < 0) {
cur = cur.left;
} else if (cmp > 0) {
cur = cur.right;
} else {
return cur;
}
}
return null;
}
}
测试代码
public class Test {
public static void main(String[] args) {
TreeNode root = new TreeNode('D');
root.left = new TreeNode('B');
root.right = new TreeNode('F');
root.left.left = new TreeNode('A');
root.left.right = new TreeNode('C');
BST bst = new BST();
bst.insert('A');
System.out.println(bst.remove('A'));
System.out.println(bst.insert('0'));
System.out.println(bst.root);
}
}