二叉树红黑树

二叉树:结构类似树。
节点:二叉树的元素。
根节点:二叉树中的第一个元素。
子节点,父节点,兄弟节点,叶子节点,左子节点,右子节点

节点的3个概念(根节点到叶子节点的最长路径计算):
高度:3,2,1,0
深度:0,1,2,3
层:1,2,3,4

树的高度等于根节点的高度。

满二叉树:1,叶子节点都在底层;2,除了叶子节点外,所有节点都有左右子节点。
完全二叉树:1,叶子节点都在最底2层;2,最后一层叶子节点都在左边;3,除了最后一层,其他叶子节点都达到最
大。


二叉树存储结构:基于链表的链式存储法,基于数组的顺序存储法。

二叉树的3种遍历,打印顺序:
前序: 节点本身→左子树→右子树
中序:左子树→节点本身→右子树
后序:左子树→右子树→节点本身


前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)

中序遍历的递推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)

后序遍历的递推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r

前序遍历(Java递归实现):
    public static void recursion(Node node) {// 前序遍历
        if (node == null) {
            return;
        }
        System.out.println(node.value);
        recursion(node.left);
        recursion(node.right);
    }

遍历的时间复杂度为O(n)


Java实现二叉树的CRUD

public class BinaryTree {

    private static class Node {
        int key;// 节点key
        Object value;// 节点value
        Node left;// 左节点
        Node right;// 右节点

        public Node(int key, Object value) {// 带参数构造函数
            this.key = key;
            this.value = value;
        }
    }

    private Node data;// 根节点

    public Object get(int key) {// 根据key查找value
        if (null == data) {
            return null;
        }

        if (key == data.key) {// 如果key等于根节点
            return data.value;
        }

        Node temp = this.data;
        while (temp != null) {// 循环二叉树的左右节点,查找key相等的value

            if (temp.key > key) {
                temp = temp.left;
            } else if (temp.key < key) {
                temp = temp.right;
            } else {
                return temp.value;
            }
        }
        return null;
    }

    public void put(int key, Object value) {// 给二叉树添加元素

        if (data == null) {// 根节点的情况
            data = new Node(key, value);
        } else {
            Node temp = this.data;

            while (temp != null) {
                if (key > temp.key) {// key大于节点key,并且节点的有子节点为null,则右子节点添加元素。
                    if (temp.right == null) {
                        temp.right = new Node(key, value);
                        return;
                    }
                    temp = temp.right;
                } else if (key < temp.key) {
                    if (temp.left == null) {
                        temp.left = new Node(key, value);
                        return;
                    }
                    temp = temp.left;
                } else {// 相等就更新(可以考虑修改为可以重复元素:1,同一个节点存入多个key,value;2
,继续遍历在下一个子节点添加元素)
                    temp.value = value;
                    return;
                }
            }
        }
    }

    public void delete(int key) {// 根据key删除元素
        if (data == null) {
            return;
        }

        Node temp = data;// 删除节点位置
        Node tempParent = null;// temp的父节点
        while (temp != null && temp.key != key) {// 获取需要删除的节点位置
            tempParent = temp;
            if (key > temp.key) {
                temp = temp.right;
            } else {
                temp = temp.left;
            }
        }

        if (temp == null) {// 如果删除的元素不存在。
            return;
        }

        // 目标节点有左右节点的情况,把右节点的最小子节点和当前节点换位置,并删除右节点的最小节点。
        if (temp.right != null && temp.left != null) {
            Node minParent = temp;
            Node min = temp.right;
            while (min.left != null) {// 循环获取右节点的最小子节点
                minParent = min;
                min = min.left;
            }
            temp.value = min.value;// 取右节点的最小子节点的值赋给当前节点
            // 后续的删除操作就是删除min了。
            temp = min;
            tempParent = minParent;

        }


        Node child = null;// temp的孩子
        if (temp.left != null) {// 如果要删除的节点只有左节点,我们只需要直接将父节点指向要删除节点的
左节点
            child = temp.left;
        } else if (temp.right != null) {

            child = temp.right;
        } else {
            // 如果要删除的节点没有子节点,我们只需要直接将父节点指向null
        }

        // 删除temp操作: 就是temp的父节点指向temp的子节点。
        if (tempParent == null) {// 删除根节点
            data = null;
        } else if (temp == tempParent.left) {// 删除的节点是父节点的左节点
            tempParent.left = child;
        } else if (temp == tempParent.right) {
            tempParent.right = child;
        }


    }

    /*
 前序遍历的递推公式:
 preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)

 中序遍历的递推公式:
 inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)

 后序遍历的递推公式:
 postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r
     */
    public static void recursion(Node node) {// 前序遍历
        if (node == null) {
            return;
        }
        System.out.println(node.value);
        recursion(node.left);
        recursion(node.right);
    }

    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
        binaryTree.put(3, "c");
        binaryTree.put(4, "d");
        binaryTree.put(5, "e");
        binaryTree.put(6, "f");

        binaryTree.delete(4);

        System.out.println(binaryTree.get(4));
        System.out.println(binaryTree.get(6));

        recursion(binaryTree.data);//遍历输出二叉树的value
    }
}

平衡二叉查找树:二叉树的任意节点的左右子树的高度差距不能大于1。

红黑树定义:
1,根节点时黑色的
2,所有叶子结点为NULL,就是不存数据
3,红色节点不能相邻,就是要被黑色节点隔开
4,每个节点到所有黑色的叶子结点的路径时一样的,红色的节点不算

红黑树就是平衡二叉树,为了减少查询的时间复杂度。红黑树的查找时间复杂度为O(n)。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值