二叉排序树 BST
二叉排序树:BTS(Binary Sort Tree),对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大。如果有相同的值,可以将该节点放在左子节点或右子节点。
二叉排序树的中序遍历,结果就是从小到大的排列。
二叉排序树的特点:
- 左子树所有的值一定比根节点小,右子树所有的值一定比根节点大
1、二叉排序树 添加
1)思路分析
- 添加的node的值小于当前节点的值,那么就判断当前节点的左节点是否为空;为空就直接挂在当前节点的左边,不为空就继续往左节点往下找
- 添加的node的值大于等于当前节点的值,那么就判断当前节点的右节点是否为空;为空就直接挂在当前节点的右边,不为空就继续往右节点往下找
2)代码实现
public class BinarySortTreeDemo {
public static void main(String[] args) {
int arr[] = {7,3,10,12,5,1,9};
BinarySortTree binarySortTree = new BinarySortTree();
for (int i = 0; i < arr.length; i++) {
binarySortTree.add(new BstNode(arr[i]));
}
binarySortTree.infixOrder();
}
}
// 二叉排序树
class BinarySortTree{
private BstNode root;
public BinarySortTree() {
}
public BinarySortTree(BstNode root) {
this.root = root;
}
public void infixOrder(){
if (root==null){
return;
}else {
root.infixOrder();
}
}
public void add(BstNode node){
if (root==null){
root = node;
}else {
root.add(node);
}
}
}
// 节点
class BstNode{
int value;
BstNode left;
BstNode right;
public BstNode(int value) {
this.value = value;
}
@Override
public String toString() {
return "BstNode{" +
"value=" + value +
'}';
}
public void infixOrder(){
if (this.left!=null){
this.left.infixOrder();
}
System.out.println(this.toString());
if (this.right!=null){
this.right.infixOrder();
}
}
// 二叉排序树添加
public void add(BstNode node){
if (node == null){
return;
}
// 添加的node的值小于当前节点的值,那么就判断当前节点的左节点是否为空
// 为空就直接挂在当前节点的左边,不为空就继续往左节点往下找
if (node.value < this.value){
if (this.left!=null){
this.left.add(node);
}else {
this.left = node;
}
}else {// 添加的node的值大于等于当前节点的值,那么就判断当前节点的右节点是否为空
// 为空就直接挂在当前节点的右边,不为空就继续往右节点往下找
if (this.right!=null){
this.right.add(node);
}else {
this.right = node;
}
}
}
}
结果:
BstNode{value=1}
BstNode{value=3}
BstNode{value=5}
BstNode{value=7}
BstNode{value=9}
BstNode{value=10}
BstNode{value=12}
2、二叉排序树 删除
1)思路分析
删除有三种情况:
-
目标节点没有任何子节点
定位到目标节点的父节点,如果目标节点是其父节点的右子节点,那么将其父节点的右子节点置为空即可;如果目标节点是父节点的左子节点,那么将其父节点的左子节点置为空即可。
-
目标节点有一个子节点
定位目标节点的父节点,如果目标节点是其父节点的左子节点,那么将其父节点的左子节点指向目标节点的子节点;如果目标节点是其父节点的右子节点,那么将其父节点的右子节点指向目标节点的子节点;如果目标节点的父节点为空,说明删除的目标节点是根节点,那么直接将根节点指向目标节点的子节点即可;。
-
目标节点有两个子节点
定位目标节点,找到目标节点的右子节点中最小的节点,将该最小的节点临时保存下来,并删除,将目标节点重新赋值为该最小的节点。
2)代码实现
public class BinarySortTreeDemo {
public static void main(String[] args) {
int arr[] = {7,3,10,12,5,1,9,2};
BinarySortTree binarySortTree = new BinarySortTree();
for (int i = 0; i < arr.length; i++) {
binarySortTree.add(new BstNode(arr[i]));
}
System.out.println("原二叉排序树中序遍历结果:");
binarySortTree.infixOrder();
System.out.println("删除有一个子节点的目标节点:1");
binarySortTree.del(1);
System.out.println("删除有两个子节点的目标节点:10");
binarySortTree.del(10);
System.out.println("删除没有子节点的目标节点:2");
binarySortTree.del(2);
System.out.println("最终中序遍历结果:");
binarySortTree.infixOrder();
}
}
// 二叉排序树
class BinarySortTree{
private BstNode root;
public BinarySortTree() {
}
public BinarySortTree(BstNode root) {
this.root = root;
}
public void infixOrder(){
if (root==null){
return;
}else {
root.infixOrder();
}
}
public void add(BstNode node){
if (root==null){
root = node;
}else {
root.add(node);
}
}
// 获得需要删除的目标节点
public BstNode getDelTargetNode(int value){
if (root==null){
return null;
}else {
return root.getDelTargetNode(value);
}
}
// 获得需要删除的目标节点的父节点
public BstNode getDelTargetParentNode(int value){
if (root==null){
return null;
}else {
return root.getDelTargetParentNode(value);
}
}
// 找最小值的节点
public BstNode getRightMinNode(BstNode node){
if (node==null){
return null;
}
while (node.left!=null){
node = node.left;
}
del(node.value); // 删除这个节点
return node;
}
// 删除节点操作
public void del(int value){
BstNode targetNode = getDelTargetNode(value);
if (targetNode == null){
return;
}
// 如果targetNode不为空,并且root节点没有左右节点肯定就是删除root节点,直接置空即可
if (root.left == null && root.right == null){
root = null;
return;
}
BstNode parentNode = getDelTargetParentNode(value);
if (targetNode.left==null && targetNode.right==null){
// 左右节点都为空,说明是叶子节点
if (parentNode.left!=null && parentNode.left.value == value){
parentNode.left = null;
}else {
parentNode.right = null;
}
}else if (targetNode.left!=null && targetNode.right!=null){
// 左右节点都不为空,说明删除的是有左右子树的节点
BstNode rightMinNode = getRightMinNode(targetNode.right);
targetNode.value = rightMinNode.value; // 把值赋给目标节点
}else {
// 说明目标节点有一个子节点
if (targetNode.left!=null){
if (parentNode!=null){
if (parentNode.left!=null && parentNode.left.value == value){
parentNode.left = targetNode.left;
}else {
parentNode.right = targetNode.left;
}
}else {
root = targetNode.left;
}
}else {
if (parentNode!=null){
if (parentNode.left!=null && parentNode.left.value == value){
parentNode.left = targetNode.right;
}else {
parentNode.right = targetNode.right;
}
}else {
root = targetNode.right;
}
}
}
}
}
// 节点
class BstNode{
int value;
BstNode left;
BstNode right;
public BstNode(int value) {
this.value = value;
}
@Override
public String toString() {
return "BstNode{" +
"value=" + value +
'}';
}
public void infixOrder(){
if (this.left!=null){
this.left.infixOrder();
}
System.out.println(this.toString());
if (this.right!=null){
this.right.infixOrder();
}
}
// 二叉排序树添加
public void add(BstNode node){
if (node == null){
return;
}
// 添加的node的值小于当前节点的值,那么就判断当前节点的左节点是否为空
// 为空就直接挂在当前节点的左边,不为空就继续往左节点往下找
if (node.value < this.value){
if (this.left!=null){
this.left.add(node);
}else {
this.left = node;
}
}else {// 添加的node的值大于等于当前节点的值,那么就判断当前节点的右节点是否为空
// 为空就直接挂在当前节点的右边,不为空就继续往右节点往下找
if (this.right!=null){
this.right.add(node);
}else {
this.right = node;
}
}
}
// 找到需要删除的目标节点
public BstNode getDelTargetNode(int value){
if (this.value == value){
return this;
}
if (value < this.value){
if (this.left!=null){
return this.left.getDelTargetNode(value);
}else {
return null;
}
}else {
if (this.right!=null){
return this.right.getDelTargetNode(value);
}else {
return null;
}
}
}
// 找到需要删除的目标节点的父节点
public BstNode getDelTargetParentNode(int value){
// 如果当前节点的左右节点中有一个的值为value,就返回该节点,就是value值节点的父节点
if (this.left!=null && this.left.value == value || this.right!=null && this.right.value == value){
return this;
}
// 不满足以上要求,说明需要继续找,
// 如果value小于当前节点的value,就在当前节点的左节点找,
// 如果value大于等于当前节点的value,就在当前节点的右节点找,
if (value < this.value){
if (this.left!=null){
return this.left.getDelTargetParentNode(value);
}else {
return null;
}
}else {
if (this.right!=null){
return this.right.getDelTargetParentNode(value);
}else {
return null;
}
}
}
}
结果:
原二叉排序树中序遍历结果:
BstNode{value=1}
BstNode{value=2}
BstNode{value=3}
BstNode{value=5}
BstNode{value=7}
BstNode{value=9}
BstNode{value=10}
BstNode{value=12}
删除有一个子节点的目标节点:1
删除有两个子节点的目标节点:10
删除没有子节点的目标节点:2
最终中序遍历结果:
BstNode{value=3}
BstNode{value=5}
BstNode{value=7}
BstNode{value=9}
BstNode{value=12}