二叉搜索树概念
二叉搜索树也可以叫做二叉排序树,一个空树也可以称为二叉搜索树。
具备以下性质:
[1]若左子树不为空,左子树上所有结点的值都小于根结点的值;
[2]若右子树不为空,则右子树上所有结点的值都大于根结点的值;
[3]一个二叉搜索树的左右子树都是二叉搜索树;
1.查找
//查找关键字为key结点 思想:向后遍历
public Node search(int val){
if(root == null) return null;
Node cur = root;
while(cur != null){
if(cur.val == val){
return cur;
}else if(cur.val < val){
cur = cur.right;
}else{
cur = cur.left;
}
}
return null;
}
2.插入
public boolean insert(int val){
Node node1 = new Node(val);
if(root == null){
root = node1;
return true;
}
Node cur = root; //cur指向根结点
Node parent = null; //用来保存遍历过的结点
while(cur != null){
parent = cur;
if(cur.val == val) return false;
if(cur.val < val){
cur = cur.right;
}else{
cur = cur.left;
}
}
if(parent.val < val){
parent.right = node1;
}else{
parent.left = node1;
}
return true;
}
3.删除(重点)
设删除结点为cur,分为三种情况:
1. cur.left为空
if(cur.left == null) {
if(cur == root) {
root = cur.right;
}else if(parent.left == cur) {
parent.left = cur.right;
}else {
parent.right = cur.right;
}
}
2. cur.right为空
if(cur.right == null) {
if(cur == root) {
root = cur.left;
}else if(parent.left == cur) {
parent.left = cur.left;
}else {
parent.right = cur.left;
}
}
3. cur.left和cur.right都不为空
在这种情况下删除结点稍微复杂了一些,怎么删除呢?按照上述两种情况的删除方法将导致一个结点会出现两个父亲结点。
在这里,采用一种“替罪羊”方式
过程:将target结点的val赋值给cur,而后将target结点删除
问题又来了,如何选择替罪羊?
在要删除结点左边找最大的结点或者在右边找最小的结点!!!
下面的代码中,我们选择在cur结点右边找小的结点方式,target分为两种情况
①target.left为空
②
if(cur.left != null && cur.right != null){
Node targetParent = cur; //targetParent指向cur
Node target = cur.right; //target指向cur.right
while (target.left != null) {
targetParent = target;
target = target.left;
}
//target指向的节点就是 右边的最小值
cur.val = target.val; //将替罪羊的val给cur
/*
分两种情况:①target.left不为空时,向后遍历,最终找到target位置
②target.left为空时,targetParent.right = target.right
*/
if(target == targetParent.left) {
targetParent.left = target.right;
}else {
targetParent.right = target.right;
}
}
删除结点完整过程
//删除结点
public void remove(int val) {
if(root == null) return;
Node cur = root;
Node parent = null;
while (cur != null) {
if(cur.val == val) {
removeNode(parent,cur,val);
return;
}else if(cur.val < val) {
parent = cur;
cur = cur.right;
}else {
parent = cur;
cur = cur.left;
}
}
}
public void removeNode(Node parent,Node cur,int val) {
if(cur.left == null) {
if(cur == root) {
root = cur.right;
}else if(parent.left == cur) {
parent.left = cur.right;
}else {
parent.right = cur.right;
}
}else if(cur.right == null) {
if(cur == root) {
root = cur.left;
}else if(parent.left == cur) {
parent.left = cur.left;
}else {
parent.right = cur.left;
}
}else {
Node targetParent = cur;
Node target = cur.right;
while (target.left != null) {
targetParent = target;
target = target.left;
}
//target指向的节点就是 右边的最小值
cur.val = target.val; //将替罪羊的val给cur
if(target == targetParent.left) {
targetParent.left = target.right;
}else {
targetParent.right = target.right;
}
}
}
2021.3.3