二叉排序树

1.背景

面试中经常问到关于树的结构

2.代码实现

package com.ldp.structure.demo07BST;

import org.junit.Test;

/**
 * @create 05/03 11:18
 * @description <p>
 * 二叉排序树
 * </p>
 */
public class Test01 {
    /**
     * 二叉排序树,添加测试
     */
    @Test
    public void test01() {
        int[] array = {7, 3, 10, 12, 5, 1, 9};
        BstTree bstTree = new BstTree();
        // 添加到二叉树
        for (int i : array) {
            bstTree.add(new Node(i));
        }
        // 中序遍历
        // bstTree.middleList();
        // 目标节点查找
        //int value = 70;
        //System.out.println("getTargetNode=>" + bstTree.getTargetNode(value));
        // 目标节点父节点查找
        // System.out.println("getTargetNodeParent=>" + bstTree.getTargetNodeParent(value));
        // 待删除的节点有零个叶子节点(本身是叶子节点)(1,5,9,12)
        // bstTree.delete(12);
        // 待删除的节点有一个叶子节点
        //bstTree.add(new Node(11));
        // bstTree.delete(12);
        //待删除的节点有两个叶子节点
        bstTree.delete(3);
        bstTree.middleList();
    }

    /**
     * 任意删除测试
     */
    @Test
    public void test02() {
        int[] array = {7, 3, 10, 12, 5, 1, 9};
        BstTree bstTree = new BstTree();
        for (int i : array) {
            bstTree.add(new Node(i));
        }
        bstTree.delete(1);
        bstTree.delete(3);

        bstTree.delete(12);
        bstTree.delete(5);
        bstTree.delete(7);
        bstTree.delete(9);
        bstTree.delete(10);
        bstTree.middleList();
    }
}

class BstTree {
    Node root;

    /**
     * 添加节点
     *
     * @param node
     */
    public void add(Node node) {
        if (root == null) {
            root = node;
        } else {
            root.add(node);
        }
    }

    /**
     * 删除节点
     *
     * @param value
     */
    public void delete(Integer value) {
        Node targetNode = getTargetNode(value);
        if (targetNode == null) {
            System.out.println("该节点不存在:value=" + value);
            return;
        }
        Node targetNodeParent = getTargetNodeParent(value);
        // 1.待删除的节点有零个叶子节点(本身是叶子节点)
        if (targetNode.leftNode == null && targetNode.rightNode == null) {
            deleteZero(targetNodeParent, value);
            System.out.println("节点删除成功:value=" + value);
        } else if (targetNode.leftNode != null && targetNode.rightNode != null) {
            // 3.待删除的节点有两个叶子节点
            deleteTwo(targetNode);
            System.out.println("节点删除成功:value=" + value);
        } else {
            // 2.待删除的节点有一个叶子节点
            deleteOne(targetNodeParent, targetNode, value);
            System.out.println("节点删除成功:value=" + value);
        }
    }

    /**
     * 待删除的节点有零个叶子节点(本身是叶子节点)
     * 1.找到待删除的节点 targetNode;
     * 2.找到targetNode的父节点 parentNode;
     * 3.判定targetNode是parentNode的左节点还是右节点
     * 如果targetNode是parentNode的左节点:parentNode.leftNode=null;
     * 如果targetNode是parentNode的右节点:parentNode.rightNode=null;
     */
    private void deleteZero(Node nodeParent, Integer value) {
        if (nodeParent == null) {
            root = null;
            return;
        }
        if (nodeParent.leftNode.value == value) {
            nodeParent.leftNode = null;
        } else {
            nodeParent.rightNode = null;
        }
    }

    /**
     * 待删除的节点有一个叶子节点
     * 1.找到待删除的节点 targetNode;
     * 2.找到targetNode的父节点 parentNode;
     * 3.判定targetNode是parentNode的左节点还是右节点
     * 如果targetNode是parentNode的左节点:
     * 且targetNode的叶子节点是左节点:parentNode.leftNode=targetNode.leftNode
     * 且targetNode的叶子节点是右节点:parentNode.leftNode=targetNode.rightNode
     * 如果targetNode是parentNode的右节点:
     * 且targetNode的叶子节点是左节点:parentNode.rightNode=targetNode.leftNode
     * 且targetNode的叶子节点是右节点:parentNode.rightNode=targetNode.rightNode
     */
    private void deleteOne(Node nodeParent, Node targetNode, Integer value) {
        Node tempNode;
        if (targetNode.leftNode != null) {// targetNode的叶子节点是左节点
            tempNode = targetNode.leftNode;
        } else {
            tempNode = targetNode.rightNode;
        }
        // 如果父节点为空
        if (nodeParent == null) {
            root = tempNode;
            return;
        }
        if (nodeParent.leftNode != null && nodeParent.leftNode.value == value) {// 如果targetNode是parentNode的左节点
            nodeParent.leftNode = tempNode;
        } else {
            nodeParent.rightNode = tempNode;
        }
    }

    /**
     * 待删除的节点有两个叶子节点
     * 1.找到待删除的节点 targetNode;
     * 2.targetNode的右节点开始找,找到最小节点
     * 3.用一个临时节点minNode保存
     * 4.删除最小节点
     * 5.targetNode.value=minNode.value
     *
     * @param targetNode
     */
    private void deleteTwo(Node targetNode) {
        Node minNodeParent = targetNode;
        Node minNode = targetNode.rightNode;
        if (targetNode.rightNode.leftNode == null) { // 如果股目标节点的右节点没有左子节点,则右节点是最小节点
            minNodeParent.rightNode = null;
            targetNode.value = minNode.value;
        } else {// 如果股目标节点的右节点有左子节点,则一直往最左边找,最后一个左节点是最小节点
            while (true) {
                if (minNode.leftNode != null) {
                    minNodeParent = minNode;
                    minNode = minNode.leftNode;
                } else {
                    break;
                }
            }
            minNodeParent.leftNode = null;
            targetNode.value = minNode.value;
        }
    }


    /**
     * 根据value找到目标节点
     *
     * @param value
     * @return
     */
    public Node getTargetNode(Integer value) {
        Node tempNode = root;
        while (tempNode != null) {
            if (tempNode.value.equals(value)) {// 已找到
                break;
            } else if (value < tempNode.value) {
                tempNode = tempNode.leftNode;
            } else {
                tempNode = tempNode.rightNode;
            }
        }
        return tempNode;
    }

    /**
     * 根据value找到目标节点的父节点
     *
     * @param value
     * @return
     */
    public Node getTargetNodeParent(Integer value) {
        if (this.root.value.equals(value)) {
            System.out.println("该节点没有父节点.....");
            return null;
        }
        Node parentNode = null;
        Node tempNode = root;
        while (tempNode != null) {
            if (tempNode.value.equals(value)) {// 已找到
                break;
            } else if (value < tempNode.value) {
                parentNode = tempNode;
                tempNode = tempNode.leftNode;
            } else {
                parentNode = tempNode;
                tempNode = tempNode.rightNode;
            }
        }
        if (tempNode == null) {
            return null;
        }
        return parentNode;
    }

    public void middleList() {
        if (root == null) {
            System.out.println("节点为空...");
        } else {
            root.middleList();
        }
    }
}

class Node {
    Integer value;
    Node leftNode;
    Node rightNode;

    public Node(Integer value) {
        this.value = value;
    }

    /**
     * 添加一个节点
     *
     * @param node
     */
    public void add(Node node) {
        if (node.value < this.value) { // 放在左边
            if (this.leftNode == null) {
                this.leftNode = node;
            } else {
                this.leftNode.add(node);
            }
        } else {// 放在右边
            if (this.rightNode == null) {
                this.rightNode = node;
            } else {
                this.rightNode.add(node);
            }
        }
    }

    /**
     * 中序遍历
     */
    public void middleList() {
        if (this.leftNode != null) {
            this.leftNode.middleList();
        }
        System.out.println(this);
        if (this.rightNode != null) {
            this.rightNode.middleList();
        }
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }
}

 

posted @ 2022-05-03 14:55  不停学  阅读(30)  评论(0)    收藏  举报