目录
- 1. 概念
- 2. 二叉搜索树的操作
- 2.1 查找
- 2.2 插入
- 2.3 删除
- 3. 全部代码
1. 概念
二叉搜索树是特殊的二叉树,也叫二叉排序树,它的特点是:每个结点的左子树上的所有结点的值都小于这个结点的值,右子树上的所有结点的值都大于这个结点的值,另外所有的左子树和右子树也分别为二叉搜索树,如图:
2. 二叉搜索树的操作
2.1 查找
根据二叉搜索树的性质来,很容易可以理解查找的逻辑:从根结点开始,比较结点的值与待查找的值,如果待查找的值比根结点的值小,说明待查找的结点一定在树的左边,如图
当然也有其他情况:根结点为空、该树不存在要查找的这个结点,这个时候直接返回null就可以了
public TreeNode search(int key) {TreeNode cur = root;while (cur != null) {if (cur.val > key) {cur = cur.left;} else if (cur.val < key) {cur = cur.right;} else {return cur;}}return null;
}
2.2 插入
插入的前提:插入一定是在叶子结点上插入,因为插入之后也要满足二叉搜索树的性质,插入之前需要查找要插入的位置,而查找的逻辑和刚才的逻辑一样
2.3 删除
删除的情况比较复杂,主要分为以下情况(假设del为要删除的结点,parent为del的父亲结点):
1、cur.left == null
- 1、del 是root
- 2、del 不是root,del是parent.left
- 3、del 不是root,del是parent.right
2、cur.right == null
- 1、del 是root
- 2、del 不是root,del是parent.left
- 3、del 不是root,del是parent.right
3、cur.left != null && cur.right != null
下面我们一个一个分析
情况1:del.left==null
-
情况1.1:del是根结点root,删除逻辑:root =del.right
-
情况1.2 :del不是根结点,del是parent.left删除逻辑:parent.left=del.right
-
情况1.3:del不是根结点,del是parent.right,删除逻辑:parent.right=del.right
情况2:del.right==null -
情况2.1:del是根结点root,删除逻辑root = del.left
-
情况2.2:del不是根结点,del是parent.left,删除逻辑:parent.left = del.left
-
情况2.3:del不是根结点,del是parent.right,删除逻辑:parent.right = del.left
情况3:要删除的结点左右都不为空
如图
两种方法:
1.找到del的左树找值最大的结点,将del结点的值替换成这个值,接着删除这个最大值的结点,如上图的37,删除之后的情况如下
2.找到del的右子树找值最小的结点,将del结点的值替换成这个值,接着删除这个最小值的结点,如上图的45,删除之后的结果如下
3. 全部代码
public class BinarySearchTree {static class TreeNode {int val;TreeNode left;TreeNode right;public TreeNode(int val) {this.val = val;}}public TreeNode root;/*** 查找** @return*/public TreeNode find(int key) {TreeNode cur = root;while (cur != null) {if (cur.val > key) {cur = cur.left;} else if (cur.val < key) {cur = cur.right;} else {return cur;}}return null;}//插入public void insert(int key) {TreeNode cur = root;TreeNode parent = null;TreeNode newNode = new TreeNode(key);if (cur == null) {root = newNode;return;}while (cur != null) {if (cur.val > key) {parent = cur;cur = cur.left;} else if (cur.val < key) {parent = cur;cur = cur.right;} else {return;}}if (parent.val > key) {parent.left = newNode;} else {parent.right = newNode;}}//删除public void delete(int key) {TreeNode cur = root;TreeNode parent = null;while (cur != null) {if (key > cur.val) {parent = cur;cur = cur.right;} else if (key < cur.val) {parent = cur;cur = cur.left;} else {//删除结点remove(parent, cur);return;}}}// 分情况讨论private void remove(TreeNode parent, TreeNode del) {//情况1:del.left==nullif (del.left == null) {//情况1.1 del是rootif (del == root) {root = del.right;} else {if (del == parent.left) {//情况1.2 del不是root,del是parent.leftparent.left = del.right;} else if (del == parent.right) {//情况1.3 del不是root,del是parent.rightparent.right = del.right;}}} else if (del.right == null) {//情况2:del.right==nullif (del == root) {//情况2.1 del是rootroot = del.left;} else {if (del == parent.left) {//情况2.2 del是parent.leftparent.left = del.left;} else if (del == parent.right) {//情况2.3 del是parent.rightparent.right = del.left;}}} else {//情况3 del.left和del.right都不为空//将del右树的值最小的结点或者左树的值最大的结点和del替换//右边找TreeNode target = del.right;TreeNode targetP = del;while (target.left != null) {targetP = target;target = target.left;}//删除之前先交换del.val = target.val;//分情况删除if (target == targetP.right) {targetP.right = target.right;}if (target == targetP.left) {targetP.left = target.right;}}}
}