二叉排序树的概念
二叉排序树(BST),对于二叉排序树的任何一个非叶子节点要求左边节点的值比当前节点的值小,右边节点的值要比当前节点的值大。当有与节点相同的值时,可以将该节点放在左子节点或者右子节点,
感觉怪怪的,哈哈哈
按照规则放之后,把一个无序的数组,放到了二叉排序树上之后,就是上图的样子。
二叉排序树的添加节点
思路:
- 将第一个节点视为根节点,当传入一个新节点时,先判断新节点和根节点的值大小
- 如果比根节点小,就放在根节点的左边,如果比根节点大,就放在根节点的右边
- 每次比较一个节点之后,都要循环递归的进行比较,找到位置后,加到节点上,然后在添加新值。
代码实现:
public void add(Noo node){
if(node==null){
return;
}
//传入节点的值和当前子树的根节点的值进行比较
if(node.no<this.no){
//如果传入的节点值小于当前节点,就把节点加在左边
if(this.left==null){
this.left=node;
}else {
//否则就递归的加入左边节点上
this.left.add(node);
}
//如果节点传入的值大于等于此值,就把此值插入右边
}else{
if(this.right==null){
this.right=node;
}else {
this.right.add(node);
}
}
}
测试代码:
package com.njupt.binaryTree;
/**
* Creat with IntelliJ IDEA
*
* @Auther:倔强的加瓦
* @Date:2021/07/29/12:46
* @Description:
*/
public class BinarySortTree {
public static void main(String[] args) {
int[] arr = {2, 7, 10, 12, 5, 1, 9};
BinarySort binarySort = new BinarySort();
//将节点添加到树上
for (int i = 0; i < arr.length; i++) {
binarySort.add(new Noo(arr[i]));
}
binarySort.inOrder();
}
}
//创建二叉树,来管理节点。
class BinarySort {
private Noo root;
public void add(Noo node) {
if (root == null) {
root = node;
} else {
root.add(node);
}
}
//中序遍历的方法
public void inOrder() {
if (root != null) {
root.inOrder();
} else {
System.out.println("节点树为空");
}
}
}
//节点信息
class Noo {
int no;
Noo left;
Noo right;
public Noo(int no) {
this.no = no;
}
@Override
public String toString() {
return "Noo{" +
"no=" + no +
'}';
}
public void add(Noo node) {
if (node == null) {
return;
}
//传入节点的值和当前子树的根节点的值进行比较
if (node.no < this.no) {
//如果传入的节点值小于当前节点,就把节点加在左边
if (this.left == null) {
this.left = node;
} else {
//否则就递归的加入左边节点上
this.left.add(node);
}
//如果节点传入的值大于等于此值,就把此值插入右边
} else {
if (this.right == null) {
this.right = node;
} else {
this.right.add(node);
}
}
}
//中序遍历的方法
public void inOrder() {
if (this.left != null) {
this.left.inOrder();
}
System.out.println(this.no);
if (this.right != null) {
this.right.inOrder();
}
}
}
中序遍历的结果测试和预期一致。
2
3
5
6
7
8
11
13
Process finished with exit code 0
二叉排序树的删除
package com.njupt.binaryTree;
/**
* Creat with IntelliJ IDEA
*
* @Auther:倔强的加瓦
* @Date:2021/07/29/12:46
* @Description:
*/
public class BinarySortTree {
public static void main(String[] args) {
int[] arr = {7, 2, 11, 13, 6, 3, 8, 5, 1};
BinarySort binarySort = new BinarySort();
//将节点添加到树上
for (int i = 0; i < arr.length; i++) {
binarySort.add(new Noo(arr[i]));
}
binarySort.inOrder();
binarySort.deleteNode(11);
binarySort.deleteNode(7);
binarySort.inOrder();
}
}
//创建二叉树,来管理节点。
class BinarySort {
private Noo root;
public void add(Noo node) {
if (root == null) {
root = node;
} else {
root.add(node);
}
}
//中序遍历的方法
public void inOrder() {
if (root != null) {
root.inOrder();
} else {
System.out.println("节点树为空");
}
}
//查找要产出的节点
public Noo search(int no) {
if (root == null) {
return null;
} else {
return root.search(no);
}
}
//查找父节点
public Noo searchParent(int no) {
if (root == null) {
return null;
} else {
return root.searchParent(no);
}
}
//找到最小节点,并删除
public int deleteRightMin(Noo node) {
Noo temp = node;
while (temp.left != null) {
temp = temp.left;
}
//此时就是找到了最小节点,删除最小节点
deleteNode(temp.no);
return temp.no;
}
//删除节点
public void deleteNode(int no) {
if (root == null) {
return;
} else {
//1需要先找到要删除的节点
Noo target = search(no);
if (target == null) {
return;
}
//如果我们发现当前这颗二叉树只有一个跟节点,并且根节点就是要删除的节点
if (root.left == null && root.right == null && root.no == no) {
root = null;
return;
}
//找父节点
Noo parent = searchParent(no);
//如果要铲除的节点是叶子节点
if (target.left == null && target.right == null) {
//需要判断子节点是父节点的左子节点还是右子节点
if (parent.left != null && parent.left.no == target.no) {
parent.left = null;
//System.out.println(target+"删除成功!");
}
if (parent.right != null && parent.right.no == target.no) {
parent.right = null;
//System.out.println(target+"删除成功!");
}
//删除两颗子树的节点
} else if (target.left != null && target.right != null) {
//从右边找一个最小的或者从左边找一个最大的,把此节点放到删除节点的位置,并且删除该节点的原始位置
int min = deleteRightMin(target.right);
target.no = min;
//删除的节点是只有一个节点
} else {
//删除节点的左边只有一个节点
if (target.left != null) {
if (parent != null) {
//删除的目标节点在父节点的左边
if (parent.left.no == no) {
parent.left = target.left;
} else {
//删除的节点在父节点的右边
parent.right = target.left;
}
} else {
root = target.left;
}
//删除的节点的右边只有一个节点
} else {
if (parent != null) {
if (parent.left.no == no) {
parent.left = target.right;
} else {
parent.right = target.right;
}
} else {
root = target.right;
}
}
}
}
}
}
//节点信息
class Noo {
int no;
Noo left;
Noo right;
public Noo(int no) {
this.no = no;
}
@Override
public String toString() {
return "Noo{" +
"no=" + no +
'}';
}
public void add(Noo node) {
if (node == null) {
return;
}
//传入节点的值和当前子树的根节点的值进行比较
if (node.no < this.no) {
//如果传入的节点值小于当前节点,就把节点加在左边
if (this.left == null) {
this.left = node;
} else {
//否则就递归的加入左边节点上
this.left.add(node);
}
//如果节点传入的值大于等于此值,就把此值插入右边
} else {
if (this.right == null) {
this.right = node;
} else {
this.right.add(node);
}
}
}
//中序遍历的方法
public void inOrder() {
if (this.left != null) {
this.left.inOrder();
}
System.out.println(this.no);
if (this.right != null) {
this.right.inOrder();
}
}
//查找要删除的节点的方法
public Noo search(int no) {
if (this.no == no) {
return this;
} else {
//如果此节点值小于目标节点,则向右找
if (this.no < no) {
if (this.right == null) {
return null;
}
return this.right.search(no);
//否则应该向左递归查找
} else {
if (this.left == null) {
return null;
}
return this.left.search(no);
}
}
}
//查找要删除节点的父节点
public Noo searchParent(int no) {
//如果当前节点的下一个节点不为空,并且就是要找的节点,则说明找到删除节点的父节点了
if ((this.left != null && this.left.no == no) || this.right != null && this.right.no == no) {
return this;
//说明没找到,应该递归往下找
} else {
if (this.no <= no && this.right != null) {
//递归向右找
return this.right.searchParent(no);
} else if (this.no > no && this.left != null) {
return this.left.searchParent(no);
} else {
return null;//没有找到父节点
}
}
}
}