- public class BinarySearchTree {
- static class TreeNode {
- public int key;
- public TreeNode left;
- public TreeNode right;
-
- public TreeNode(int key) {
- this.key = key;
- }
- }
- public TreeNode root;
- }
- public boolean insert(int key) {
- if(this.root == null) {
- this.root = new TreeNode(key);
- return true;
- }
- TreeNode cur = this.root;
- TreeNode parent = null;
- //找到插入位置的父亲
- while(cur != null) {
- if(cur.key < key) {
- parent = cur;
- cur = cur.right;//往右走
- } else if(cur.key > key) {
- parent = cur;
- cur = cur.left;//往左走
- } else {
- //不能插入相同的元素
- return false;
- }
- }
- TreeNode node = new TreeNode(key);
- if(key > parent.key) {
- parent.right = node;
- } else {
- parent.left = node;
- }
- return true;
- }

- public TreeNode search(int key) {
- TreeNode cur = root;
- while(cur != null) {
- if(cur.key > key) {
- cur = cur.left;
- } else if(cur.key < key) {
- cur = cur.right;
- } else {
- return cur;
- }
- }
- return null;
- }
查找函数相对比较简单,就是个二分查找。
- public boolean remove(int key) {
- TreeNode cur = root;
- TreeNode parent = null;
- while(cur != null) {
- if(cur.key > key) {
- parent = cur;
- cur = cur.left;
- } else if(cur.key < key) {
- parent = cur;
- cur = cur.right;
- } else {
- removeNode(parent, cur);
- return true;
- }
- }
- return false;
- }
- private void removeNode(TreeNode parent, TreeNode cur) {
- //1.左为空 2.右为空 3.都不为空
- if(cur.left == null) {
- if(cur == root) {
- root = cur.right;
- } else if(cur == parent.right) {
- parent.right = cur.right;
- } else {
- parent.left = cur.right;
- }
- } else if(cur.right == null) {
- if(cur == root) {
- root = cur.left;
- }else if(cur == parent.left) {
- parent.left = cur.left;
- } else {
- parent.right = cur.left;
- }
- } else {
- TreeNode targetParent = cur;
- TreeNode target = cur.right;
- //可以在待删除结点的左子树找一个最大值将其覆盖,也可以在待删除结点的右子树找一棵最小的值将其覆盖,最后删除替罪羊
- while(target.left != null) {
- targetParent = target;
- target = target.left;
- }
- cur.key = target.key;
- //判断替罪羊是targetParent的左孩子还是右孩子
- if(target == targetParent.left) {
- targetParent.left = target.right;
- } else {
- targetParent.right = target.right;
- }
- }
- }
分情况讨论:设待删除结点为 cur ,待删除结点为 parent 。
1.cur.left == null
- cur == root
- cur == parent.left
- ccur == parent.right
2.cur.right == null
- cur == root
- cur == parent.left;
- cur == parent.right
3.cur.left != null && cur.right != null
- 替换法(难点)
画图解释替换法!


当带删除元素key有左右孩子的时候,直接把key删除是不现实的,因为你根本不知到key下面的结构是什么,就算知道,调整起来也无从下手,所以我们需要借助替换法来实现,既可以选择key的左子树中的最大值进行替换,也可以选择key的右子树中最小值进行替换,因为这样才能保证二叉搜索树的结构不被破坏。
下图中序遍历的结果为:0,1,2,3,4,5,6,7,8,9

- public List<Integer> inOrder(TreeNode root) {
- List<Integer> list = new ArrayList<>();
- if(root == null) {
- return list;
- }
- List<Integer> left = inOrder(root.left);
- list.addAll(left);//左
- list.add(root.key);//中
- List<Integer> right = inOrder(root.right);
- list.addAll(right);//右
- return list;
- }
咱们在对二叉搜索树进行CURD操作时,就可以通过调用中序遍历的调试和打印来判断是否正确!
本期博客就到这里了,下期再见!!!