美文网首页
二叉查找树代码实现

二叉查找树代码实现

作者: VictorBXv | 来源:发表于2018-02-07 23:04 被阅读0次

一、定义

  1. 查找二叉树又叫二叉排序树,如果同时满足以下性质:
    1. 左右子树都是二叉树
    2. 如果左子树不为空,那么左子树上面的所有节点的关键字都比根节点的关键字小;
    3. 如果右子树不为空,那么右子树上面的所有节点的关键字都比跟节点的关键字大;
  2. 好处:方便查找,可以提高查找效率,查找二叉树越平衡,查找的效率的越稳定,效率越高,这种树就是平衡二叉树

二、代码实现

public class SearchBinaryTree {

    private TreeNode root;//跟节点

    /**
     * 创建查找二叉树,如果关键字比根节点的关键字大,就往右边插入,
     * 如果关键字比根节点小,就往左边插入
     * @param data 带插入的数据
     * @return
     */
    public TreeNode put(int data) {
        TreeNode node = null;
        TreeNode parent = null;
        //首先判断根节点,如果根节点为空,则新创建的节点为根节点
        if (root == null) {
            node = new TreeNode(0, data);
            root = node;
            return node;
        } else {
            //如果不是根节点,就需要不停地遍历已有的节点,找到满足条件的节点的位置,然后插入节点
            //和根节点进行比较,首先要拿到根节点
            node = root;
            while (node != null) {
                //把当前结点制定为父节点,然后比较左右孩子和当前节点的大小
                parent = node;
                //如果要插入的数据比当前结点要大,就需要往右子树上找
                if (data > node.data) {
                    node = node.rightChild;
                } else if (data < node.data) {
                    node = node.leftChild;
                } else {
                    return node;
                }
            }
            //while循环结束,就表示找到了要插入的地方,
            // 接下来就是创建节点,然后把这个节点挂在指定的位置
            //角标默认是0
            node = new TreeNode(0, data);
            //节点创建完毕,需要判断放在父节点的左边还是右边
            if (data < parent.data) {
                parent.leftChild = node;
            } else {
                parent.rightChild = node;
            }
            //指定这个节点的父节点
            node.parent = parent;
            return node;
        }
    }

    /**
     * 删除二叉查找树中的某个节点,
     * <strong>因为是二叉查找树,所以是删除某个节点后,需要对剩下的节点进行
     * 重新排序,使之依然是二叉查找树
     * </strong>
     * @param data
     */
    public void deleteNode(int data) {
        //要想删除某个节点,必须先找到这个节点
        TreeNode node = searchNode(data);
        //如果node为空,表示没有找到
        if (node == null) {
            throw new NoSuchElementException("没有指定的节点");
        } else {
            delete(node);
        }
    }

    /**
     * 删除节点
     * @param node 要删除的节点
     */
    private void delete(TreeNode node) {
        if (node == null) {
            throw new NoSuchElementException("没有这个节点");
        } else {
            //如果当前节点不为空,就需要判断这个节点的父节点,左右孩子节点是否为空
            TreeNode parent = node.parent;
            //如果 当前节点为叶子节点,直接删除
            if (node.leftChild == null && node.rightChild == null) {
                //需要判断是父亲的左儿子还是右儿子
                if (parent.leftChild == node) {
                    parent.leftChild = null;
                    node.parent = null;
                } else {
                    parent.rightChild = null;
                    node.parent = null;
                }
            } else if (node.leftChild != null && node.rightChild == null) {
                //如果被删除的节点有左孩子没有右孩子
                //这是还需要判断这个节点是在父节点的左子树上,还是在右子树上
                //如果这个节点在左子树上,就需要把这个节点的左孩子放在parent的左子树上
                if (parent.leftChild == node) {
                    parent.leftChild = node.leftChild;
                } else {
                    parent.rightChild = node.leftChild;
                }
            } else if (node.leftChild == null && node.rightChild != null) {
                //如果被删除的节点有右孩子而没有左孩子
                if (parent.leftChild == node) {
                    parent.leftChild = node.rightChild;
                } else {
                    parent.rightChild = node.rightChild;
                }
            } else if (node.leftChild != null && node.rightChild != null) {
                //如果被删除的节点既有左孩子又有右孩子
                //找后继节点
                TreeNode next = getNextNode(node);
                delete(next);
                node.data = next.data;
            }
        }
    }

    /**
     * 找到某个节点的后继节点
     * @param node
     * @return
     */
    private TreeNode getNextNode(TreeNode node) {
        if (node == null) {
            return null;
        } else {
            //如果这个节点的右子树不为空,就在右子树里面找到key最小的节点
            if (node.rightChild != null) {
                return getMinTreeNode(node);
            } else {
                TreeNode parent = node.parent;
                while (parent == null && node == parent.rightChild) {
                    node = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        }
    }

    /**
     * 找到这个节点的子树下面key最小的节点,最小的节点一定在该节点的左子树上的最末端
     * @param node
     * @return
     */
    private TreeNode getMinTreeNode(TreeNode node) {
        if (node == null) {
            return null;
        } else {
            while (node.leftChild != null) {
                node = node.leftChild;
            }
        }
        return node;
    }

    private TreeNode searchNode(int data) {
        TreeNode node;
        //先从根节点开始找
        node = root;
        if (node == null) {
            return null;
        } else {
            while (node != null && data != node.data) {
                if (data > node.data) {
                    node = node.rightChild;
                } else if (data < node.data) {
                    node = node.leftChild;
                } else {
                    return node;
                }
            }
            //当while循环结束后,就表示已经遍历完了整个二叉查找树,
            // 有可能找到,有可能找不到,即node有可能为null
            return node;
        }
    }

    /**
     * 中序遍历二叉查找树,如果树构建的正确,中序遍历出来应该是升序的
     * @param node
     */
    public void midOrderTraverse(TreeNode node) {
        midOrderTraverse(node.leftChild);
        System.out.print(node.data + " ");
        midOrderTraverse(node.rightChild);
    }

    private static final class TreeNode {
        private int key;//二叉查找树的关键字,通过这个关键字对节点进行排序
        private TreeNode leftChild;
        private TreeNode rightChild;
        private TreeNode parent;
        private int data;

        public TreeNode(int key, int data) {
            this.key = key;
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
            this.parent = null;
        }

        public int getKey() {
            return key;
        }

        public void setKey(int key) {
            this.key = key;
        }

        public TreeNode getLeftChild() {
            return leftChild;
        }

        public void setLeftChild(TreeNode leftChild) {
            this.leftChild = leftChild;
        }

        public TreeNode getRightChild() {
            return rightChild;
        }

        public void setRightChild(TreeNode rightChild) {
            this.rightChild = rightChild;
        }

        public TreeNode getParent() {
            return parent;
        }

        public void setParent(TreeNode parent) {
            this.parent = parent;
        }

        public int getData() {
            return data;
        }

        public void setData(int data) {
            this.data = data;
        }
    }
}

相关文章

  • 二叉查找树

    1)二叉查找树是什么?2)二叉查找树的插入、删除、查找?3)Go代码实现 一、二叉查找树是什么?二叉查找树(BST...

  • 7天练|Day5:二叉树和堆

    关于二叉树和堆的7个必知必会的代码实现二叉树实现一个二叉查找树,并且支持插入、删除、查找操作实现查找二叉查找树中某...

  • 二叉树 堆 2019-04-17

    二叉树 实现一个二叉查找树,并且支持插入、删除、查找操作 实现查找二叉查找树中某个节点的后继、前驱节点 实现二叉树...

  • 平衡二叉查找树-AVL树代码实现

    平衡二叉查找树-AVL树代码实现 什么是“平衡二叉查找树”? 平衡二叉树的严格定义是这样的:二叉树中任意一个节点的...

  • 二叉查找树的查找和排序方法的实现

    定义二叉树 二叉查找树的查找和排序方法的实现

  • 6. 二叉树创建-查找

    1. 递归方式实现二叉树的构建2. 树、二叉树、二叉查找树3. 二叉树排序树的理解4. 二叉查找树5. 二叉树的查找

  • 树 - 二叉查找树

    二叉查找树也叫二叉搜索树,是二叉树中最常见的一种类型。顾名思义,二叉查找树是为了实现快速查找而生的,当然,它不仅仅...

  • 二叉查找树

    二叉查找树是二叉树中最常用的一种类型,也叫二叉搜索树。顾名思义,二叉查找树是为了实现快速查找而生的。不过,它不仅仅...

  • 极客时间数据结构与算法之美笔记25~26

    二叉树到二叉查找树,是为了查找数据的效率接近logN。 二叉查找树到平衡二叉查找树,是为了防止二叉查找树沦为链表。...

  • 二叉查找树代码实现

    一、定义 查找二叉树又叫二叉排序树,如果同时满足以下性质:左右子树都是二叉树;如果左子树不为空,那么左子树上面的所...

网友评论

      本文标题:二叉查找树代码实现

      本文链接:https://www.haomeiwen.com/subject/yekzzxtx.html