[Reservado] árboles binarios y ordenar árbol binario equilibrado detallada

I. Introducción

  En estos días quieren aprender Javaestructuras de datos son ampliamente utilizados en - árboles negros, pero el blog reloj dice que necesita saber antes de estudiar rojo-negro de árboles árboles binarios ordenar y árbol binario equilibrado , por lo que pasé algún caso estas dos estructuras de datos a aprender de nuevo, pero también un poco de ambos para alcanzar sus propias estructuras de datos. Podemos decir que se trata de dos estructuras de datos relativamente complejos, especialmente el árbol binario equilibrado. Afortunadamente, me encontré con dos muy buen blog de explicar, pero el propósito de este blog es que quiero a querer aprender estas dos personas dos estructuras de datos recomiendan este blog, por cierto también está haciendo una marca por sí mismo , fácil de leer de nuevo más tarde.


En segundo lugar, el texto

  En primer lugar adjuntar enlaces de estos dos blog:

  Estos dos blog para explicar estas dos estructuras de datos está muy claro, en particular, es el segundo de árbol de equilibrio, me siento realmente hablar es completamente de punto. Para aprender árbol binario balanceado, me encontré con una gran parte del blog de Internet, pero explico no son muy claras, sobre todo porque la mayor parte del blog se citó ejemplos no tienen universal, y es marcadamente por encima de este blog. El punto más importante es que estos dos códigos blog escrito en el bien, para el logro de estas dos estructuras de datos están muy refinado, la sensación es la forma más conveniente para lograr sacarlos. Y estos dos blog está escrito por el mismo autor, árbol binario balanceado es un árbol binario de búsqueda mejorada versión del blog mientras que el segundo código se basa en el primer capítulo de la modificación de sólo leer el primer capítulo de el segundo código será más fácil de entender .


En tercer lugar, el código

  El código de dos el blog anterior se pythonescribe, me refiero a la utilización Javade escribir de nuevo, no pythonpuede referirse también a Javaun código, la lógica es la misma (copiar el código demasiado tiempo para recomendar al compilador para ver).

(1) árbol de tipo binario

/**
 * 实现二叉排序树(二叉搜索树)
 */
public class BinarySearchTree {

    private TreeNode root;

    /**
     * 树节点
     */
    static class TreeNode {
        private int value;
        private TreeNode lchild;
        private TreeNode rchild;

        public TreeNode(int value) {
            this.value = value;
        }

        public TreeNode(int value, TreeNode lchild, TreeNode rchild) {
            this.value = value;
            this.lchild = lchild;
            this.rchild = rchild;
        }
    }


    public void traversal() {
        traversal(root);
        System.out.println();
    }

    /**
     * 中序遍历
     *
     * @param root
     */
    private void traversal(TreeNode root) {
        if (root == null)
            return;
        traversal(root.lchild);
        System.out.print(root.value + " ");
        traversal(root.rchild);
    }


    /**
     * 插入数据
     *
     * @param value
     */
    public void insert(int value) {
        root = insert(root, value);
    }

    private TreeNode insert(TreeNode root, int value) {
        if (root == null)
            return new TreeNode(value);

        // 若需要插入的节点值小于当前遍历到的节点值,则向做递归
        if (value < root.value)
            root.lchild = insert(root.lchild, value);
        else
            root.rchild = insert(root.rchild, value);
        return root;
    }


    /**
     * 根据节点值删除节点
     *
     * @param value
     * @return
     */
    public void delete(int value) {
        root = delete(root, value);
    }

    /**
     * 删除值为value的节点
     *
     * @param root  当前遍历到的节点
     * @param value 需要删除的节点的value值
     */
    private TreeNode delete(TreeNode root, int value) {
        if (root == null)
            return null;

        if (value < root.value)
            root.lchild = delete(root.lchild, value);
        else if (value > root.value)
            root.rchild = delete(root.rchild, value);
        else {
            // 若找到需要删除的节点,则根据节点的子节点数量,判断删除的方法
            // 若当前节点有两个子节点,则将当前节点的左子树中最大的节点覆盖当前节点,
            // 然后将这个子节点删除
            if (root.lchild != null && root.rchild != null) {
                // 找到当前节点的左子树中,最大的节点
                TreeNode maxChild = root.lchild;
                while (maxChild.rchild != null)
                    maxChild = maxChild.rchild;
                // 删除这个当前节点
                root = delete(root, maxChild.value);
                // 将当前节点值改为最大子节点的值
                root.value = maxChild.value;
            } else {
                // 若需要删除的节点有0或1个直接子节点,则直接让它的子节点替换它
                root = (null == root.lchild ? root.rchild : root.lchild);
            }
        }
        return root;
    }

}


(2) equilibrado árbol binario

/**
 * 平衡二叉树的Java实现
 */
public class BalancedBinaryTree {

    /**
     * 树的根节点
     */
    private TreeNode root;

    /**
     * 树节点
     */
    static class TreeNode {
        private int value;
        private int height;
        private TreeNode lchild;
        private TreeNode rchild;

        public TreeNode(int value) {
            this.value = value;
        }

        public TreeNode(int value, int height) {
            this.value = value;
            this.height = height;
        }
    }


    /**
     * 中序遍历当前的平衡二叉树
     */
    public void traversal() {
        traversal(root);
        System.out.println();
    }

    /**
     * 遍历以当前节点为根节点的平衡二叉树
     * 中序遍历
     * @param root
     */
    private void traversal(TreeNode root) {
        if (null == root)
            return;

        traversal(root.lchild);
        System.out.print(root.value + " ");
        traversal(root.rchild);
    }


    /**
     * 在平衡二叉树中新增加节点
     * @param value
     */
    public void insert(int value) {
        root = insert(root, value);
    }

    /**
     * 在以当前节点为根节点的平衡二叉树中新增节点
     * @param root 当前根节点
     * @param value 需要新增节点的value
     */
    private TreeNode insert(TreeNode root, int value) {
        if (null == root)
            return new TreeNode(value);

        if (value < root.value)
            root.lchild = insert(root.lchild, value);
        else
            root.rchild = insert(root.rchild, value);
        // 插入完成后判断当前节点的平衡性
        return checkBalance(root);
    }


    /**
     * 删除节点值为value的节点
     * @param value 需要删除节点的节点值
     * @return
     */
    public void delete(int value) {
        root = delete(root, value);
    }


    /**
     * 从根节点为root的子树中,删除节点值为value的节点
     * @param root
     * @param value
     * @return
     */
    private TreeNode delete(TreeNode root, int value) {
        if (null == root)
            return null;

        if (value < root.value)
            root.lchild = delete(root.lchild, value);
        else if (value > root.value)
            root.rchild = delete(root.rchild, value);
        else {
            /* 找到需要删除的节点后,判断这个节点的子节点的数量
               子节点数量为0,直接输出;为1,用子节点替代自己
               若子节点数目为2,分两种情况考虑:
                 1、左子树更深,则使用左子树中做大的节点替代根节点;
                 2、右子树更深,则使用右子树中最小的节点替代根节点;
             */
            if (null != root.lchild && null != root.rchild) {
                TreeNode newRoot = getNewRoot(root);
                root = delete(root, newRoot.value);
                root.value = newRoot.value;
            } else
                root = (null == root.lchild ? root.rchild : root.lchild);
        }
        return checkBalance(root);
    }


    /**
     * 在删除节点的操作中,若需要删除的节点右两个子节点,
     * 则需要找出一个节点直接替代需要深处的节点
     * 可以是左子树中最大的节点,也可以是右子树中最小的节点,根据左右子树的深度判断
     * @param root
     * @return
     */
    private TreeNode getNewRoot(TreeNode root) {
        TreeNode node = null;
        // 左子树更深
        if (root.lchild.height > root.rchild.height) {
            node = root.lchild;
            while (null != node.rchild)
                node = node.rchild;
        } else {
            node = root.rchild;
            while (null != node.lchild)
                node = node.lchild;
        }
        return node;
    }


    /**
     * 判断以当前节点为根节点的子树的平衡性
     * @param root 当前子树的根节点
     * @return 返回根节点
     */
    private TreeNode checkBalance(TreeNode root) {
        if (null == root)
            return null;

        // 根据当前节点的左右节点的高度差来判断平衡性
        int diff = getHeightDiff(root);
        if (diff < 2)
            updateHeight(root);
        // 失衡,左深右浅
        else if (diff == 2) {
            int ldiff = getHeightDiff(root.lchild);
            // LL型失衡,直接右旋
            if (ldiff == 1) {
                root = RotateRight(root);
            // LR型失衡,将右节点左旋,在将当前节点右旋
            } else if(ldiff == -1){
                root.rchild = RotateLeft(root.rchild);
                root = RotateLeft(root);
            } else
                throw new RuntimeException("diff is error");

        } else if (diff == -2) {    // 失衡,右深左浅
            int rdiff = getHeightDiff(root.rchild);
            // RR失衡,直接左旋
            if (rdiff == -1)
                root = RotateLeft(root);
            // RL失衡,先root的右节点右旋,然后root左旋
            else if (rdiff == 1) {
                root.rchild = RotateRight(root.rchild);
                root = RotateLeft(root);
            }

        } else
            throw new RuntimeException("diff is error");

        return root;
    }

    /**
     * 获取当前节点的左右子树的高度差
     * @param root
     * @return
     */
    private int getHeightDiff(TreeNode root) {
        // 有两个子节点
        if (null != root.lchild && null != root.rchild)
            return root.lchild.height - root.rchild.height;
        // 只有左子节点
        else if (null != root.lchild)
            return root.lchild.height + 1;
        // 只有右子节点
        else if (null != root.rchild)
            return root.rchild.height + 1;
        // 无子节点
        return 0;
    }

    /**
     * 在插入或者删除节点后,更新当前节点的高度
     * @param root
     */
    private void updateHeight(TreeNode root) {
        // 有两个子节点
        if (null != root.lchild && null != root.rchild)
            root.height = Math.max( root.lchild.height, root.rchild.height ) + 1;
            // 只有左子节点
        else if (null != root.lchild)
            root.height = root.lchild.height + 1;
            // 只有右子节点
        else if (null != root.rchild)
            root.height = root.rchild.height + 1;
        // 无子节点
        root.height = 0;
    }


    /**
     * 将当前节点为根的子树进行右旋
     * @param root
     */
    private TreeNode RotateRight(TreeNode root) {
        TreeNode newRoot = root.lchild;
        root.lchild = newRoot.rchild;
        newRoot.rchild = root;
        updateHeight(root);
        updateHeight(newRoot);
        return newRoot;
    }


    /**
     * 将当前节点为根的子树进行左旋
     * @param root
     * @return
     */
    private TreeNode RotateLeft(TreeNode root) {
        TreeNode newRoot = root.rchild;
        root.rchild = newRoot.lchild;
        newRoot.lchild = root;
        updateHeight(root);
        updateHeight(newRoot);
        return newRoot;
    }

}

Supongo que te gusta

Origin www.cnblogs.com/tuyang1129/p/12536314.html
Recomendado
Clasificación