二叉树与红黑树的java实现

二叉树的java实现

public class BinaryTree {

    /**
     * 根节点
     */
    private static Node root;

    static class Node {
        int key;
        Node left, right, parent;

        public Node(int key) {
            this.key = key;
        }
    }

    public BinaryTree(int key) {
        root = new Node(key);
    }

    /**
     * 中序遍历
     *
     * @param node 根节点
     */
    public void inOrderTreeWalk(Node node) {
        if (node != null) {
            inOrderTreeWalk(node.left);
            System.out.print(node.key + ",");
            inOrderTreeWalk(node.right);
        }
    }

    /**
     * 查找
     *
     * @param node 根节点
     * @param key 查找值
     * @return
     */
    public Node treeSearch(Node node, int key) {
        while (node != null && key != node.key) {
            if (key < node.key) {
                node = node.left;
            } else {
                node = node.right;
            }
        }
        return node;
    }

    /**
     * 最小值
     *
     * @param node 根节点
     * @return
     */
    public Node treeMinimum(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    /**
     * 最大值
     *
     * @param node 根节点
     * @return
     */
    public Node treeMaximum(Node node) {
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }

    /**
     * 前驱
     *
     * @param node 根节点
     * @return
     */
    public Node treePredecessor(Node node) {
        // 如果存在左子树,返回左子树的最大值
        if (node.left != null) {
            return treeMaximum(node.left);
        }
        Node y = node.parent;
        // 当不存在左子树时,返回最低祖先节点
        while (y != null && node == y.left) {
            node = y;
            y = y.parent;
        }
        return y;
    }

    /**
     * 后继
     *
     * @param node 根节点
     * @return
     */
    public Node treeSuccessor(Node node) {
        // 如果存在右子树,返回右子树的最小值
        if (node.right != null) {
            return treeMinimum(node.right);
        }
        Node y = node.parent;
        // 当不存在右子树时,返回最低祖先节点
        while (y != null && node == y.right) {
            node = y;
            y = y.parent;
        }
        return y;
    }

    /**
     * 插入
     *
     * @param key 插入节点的关键值
     */
    public void treeInsert(int key) {
        // 创建插入节点
        Node node = new Node(key);
        // 定义插入节点的父节点变量
        Node y = null;
        // 定义临时变量存根节点
        Node x = root;
        // 在根节点的左、右子树中查找插入位置
        while (x != null) {
            y = x;
            if (key < x.key) {
                x = x.left;
            } else {
                x = x.right;
            }
        }
        node.parent = y;
        if (y == null) {
            root = node;
        } else if (key < y.key) {
            y.left = node;
        } else {
            y.right = node;
        }
    }

    /**
     * 删除
     *
     * @param node 删除节点
     * @return
     */
    public Node treeDelete(Node node) {
        // 定义临时变量存删除节点或后继节点
        Node y;
        // 当删除节点至多有一个孩子时
        if (node.left == null || node.right == null) {
            y = node;
        } else {// 当删除节点有两个孩子时,y存后继节点
            y = treeSuccessor(node);
        }
        // 定义临时变量存删除节点的孩子节点
        Node x;
        if (y.left != null) {
            x = y.left;
        } else {
            x = y.right;
        }
        if (x != null) {
            x.parent = y.parent;
        }
        if (y.parent == null) {
            root = x;
        } else if (y == y.parent.left) {
            y.parent.left = x;
        } else {
            y.parent.right = x;
        }
        // 当y为后继节点时,将y的关键值赋给删除节点
        if (y != node) {
            node.key = y.key;
        }
        return y;
    }

}

红黑树的java实现(备注:中序遍历、查找、最大、最小、前驱、后继与二叉树基本一致)

public class RBTree {

    /**
     * 根节点
     */
    private static Node root;

    /**
     * nil节点是红黑树的叶子节点不同于二叉树的叶子节点
     * 颜色为黑色,key、left、right、parent可以是任意允许的值
     * 这里key设置为0,left、right、parent为null
     */
    private Node nil = new Node(true);

    static class Node {
        int key;
        Node left, right, parent;
        boolean color;// true黑,false红

        public Node(int key) {
            this.key = key;
        }

        public Node(boolean color) {
            this.color = color;
        }

        public boolean equals(Node node) {
            return this.key == node.key;
        }
    }

    public RBTree(int key) {
        root = new Node(key);
    }

    /**
     * 中序遍历
     *
     * @param node 根节点
     */
    public void inOrderTreeWalk(Node node) {
        if (node != null && !node.equals(nil)) {
            inOrderTreeWalk(node.left);
            System.out.print((node.color == true ? "黑" : "红") + node.key + ",");
            inOrderTreeWalk(node.right);
        }
    }

    /**
     * 查找
     *
     * @param node 根节点
     * @param key 查找值
     * @return
     */
    public Node treeSearch(Node node, int key) {
        while (node != null && key != node.key) {
            if (key < node.key) {
                node = node.left;
            } else {
                node = node.right;
            }
        }
        return node;
    }

    /**
     * 最小值
     *
     * @param node 根节点
     * @return
     */
    public Node treeMinimum(Node node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    /**
     * 最大值
     *
     * @param node 根节点
     * @return
     */
    public Node treeMaximum(Node node) {
        while (node.right != null) {
            node = node.right;
        }
        return node;
    }

    /**
     * 前驱
     *
     * @param node 根节点
     * @return
     */
    public Node treePredecessor(Node node) {
        // 如果存在左子树,返回左子树的最大值
        if (node.left != null) {
            return treeMaximum(node.left);
        }
        Node y = node.parent;
        // 当不存在左子树时,返回最低祖先节点
        while (y != null && node == y.left) {
            node = y;
            y = y.parent;
        }
        return y;
    }

    /**
     * 后继
     *
     * @param node 根节点
     * @return
     */
    public Node treeSuccessor(Node node) {
        // 如果存在右子树,返回右子树的最小值
        if (node.right != null) {
            return treeMinimum(node.right);
        }
        Node y = node.parent;
        // 当不存在右子树时,返回最低祖先节点
        while (y != null && node == y.right) {
            node = y;
            y = y.parent;
        }
        return y;
    }

    /**
     * 左旋(node节点必有右孩子)
     *
     * @param node
     */
    public void leftTotate(Node node) {
        Node y = node.right;
        node.right = y.left;
        if (y.left != null)
            y.left.parent = node;
        y.parent = node.parent;
        if (node.parent == null) {
            root = y;
        } else if (node == node.parent.left) {
            node.parent.left = y;
        } else {
            node.parent.right = y;
        }
        node.parent = y;
        y.left = node;
    }

    /**
     * 右旋(node节点必有左孩子)
     *
     * @param node
     */
    public void rightTotate(Node node) {
        Node y = node.left;
        node.left = y.right;
        if (y.right != null)
            y.right.parent = node;
        y.parent = node.parent;
        if (node.parent == null) {
            root = y;
        } else if (node == node.parent.left) {
            node.parent.left = y;
        } else {
            node.parent.right = y;
        }
        node.parent = y;
        y.right = node;
    }

    /**
     * 插入
     *
     * @param key 插入节点的关键值
     */
    public void RBTreeInsert(int key) {
        // 创建插入节点
        Node node = new Node(key);
        // 定义插入节点的父节点变量
        Node y = null;
        // 定义临时变量存根节点
        Node x = root;
        // 在根节点的左、右子树中查找插入位置
        while (x != null) {
            y = x;
            if (key < x.key) {
                x = x.left;
            } else {
                x = x.right;
            }
        }
        node.parent = y;
        if (y == null) {
            root = node;
        } else if (key < y.key) {
            y.left = node;
        } else {
            y.right = node;
        }
        RBTreeInsertFixup(node);
    }

    /**
     * 插入后修复
     *
     * @param node 插入节点
     */
    public void RBTreeInsertFixup(Node node) {
        // 当插入节点的父节点为红色时,执行循环
        while (node.parent != null && !node.parent.color && node.parent.parent != null) {
            // 当插入节点的父节点为其爷爷节点的左孩子时
            if (node.parent == node.parent.parent.left) {
                // 定义y存叔叔节点
                Node y = node.parent.parent.right;
                // 如果叔叔节点为红色,将父节点与叔叔节点变成黑色,爷爷节点变成红色,将插入节点升级为爷爷节点
                if (y != null && !y.color) {
                    node.parent.color = true;
                    y.color = true;
                    node.parent.parent.color = false;
                    node = node.parent.parent;
                } else if (node == node.parent.right) {//如果叔叔节点为黑色,插入节点是父节点的右孩子,将插入节点升级为父节点,左旋插入节点
                    node = node.parent;
                    leftTotate(node);
                } else {//如果叔叔节点为黑色,插入节点是父节点的左孩子,将父节点变成黑色,爷爷节点变成红色,右旋爷爷节点
                    node.parent.color = true;
                    node.parent.parent.color = false;
                    rightTotate(node.parent.parent);
                }
            } else {// 当插入节点的父节点为其爷爷节点的右孩子时
                // 定义y存叔叔节点
                Node y = node.parent.parent.left;
                // 如果叔叔节点为红色,将父节点与叔叔节点变成黑色,爷爷节点变成红色,将插入节点升级为爷爷节点
                if (y != null && !y.color) {
                    node.parent.color = true;
                    y.color = true;
                    node.parent.parent.color = false;
                    node = node.parent.parent;
                } else if (node == node.parent.left) {//如果叔叔节点为黑色,插入节点是父节点的左孩子,将插入节点升级为父节点,右旋插入节点
                    node = node.parent;
                    rightTotate(node);
                } else {//如果叔叔节点为黑色,插入节点是父节点的右孩子,将父节点变成黑色,爷爷节点变成红色,左旋爷爷节点
                    node.parent.color = true;
                    node.parent.parent.color = false;
                    leftTotate(node.parent.parent);
                }
            }
        }
        // 将根节点变成黑色
        if (root.parent != null) {
            root = root.parent;
        }
        root.color = true;
    }

    /**
     * 删除
     *
     * @param node 删除节点
     * @return
     */
    public Node RBTreeDelete(Node node) {
        // 定义临时变量存删除节点或后继节点
        Node y;
        // 当删除节点至多有一个孩子时
        if (node.left == null || node.right == null) {
            y = node;
        } else {// 当删除节点有两个孩子时,y存后继节点
            y = treeSuccessor(node);
        }
        // 定义临时变量存删除节点的孩子节点
        Node x;
        if (y.left != null) {
            x = y.left;
        } else {
            x = y.right;
        }
        if (x != null) {
            x.parent = y.parent;
        } else {
            x = nil;
            x.parent = y.parent;
        }
        if (y.parent == null) {
            root = x;
        } else if (y == y.parent.left) {
            y.parent.left = x;
        } else {
            y.parent.right = x;
        }
        // 当y为后继节点时,将y的关键值赋给删除节点
        if (y != node) {
            node.key = y.key;
        }
        // 当y为黑色时,需要修复红黑树
        if (y.color) {
            RBTreeDeleteFixup(x);
        }
        return y;
    }

    /**
     * 删除后修复
     *
     * @param node 删除节点的孩子节点
     */
    public void RBTreeDeleteFixup(Node node) {
        // 当node不等于根节点并且为黑色时,执行循环
        while (node != root && (node == nil || node.color)) {
            // 如果node节点为父节点的左孩子
            if (node == node.parent.left) {
                // 定义w存兄弟节点
                Node w = node.parent.right;
                // 当兄弟节点为红色时,将兄弟节点变成黑色,父节点变成红色,左旋父节点,更新兄弟节点
                if (!w.color) {
                    w.color = true;
                    node.parent.color = false;
                    leftTotate(node.parent);
                    w = node.parent.right;
                } else if (w.left.color && w.right.color) {//当兄弟节点为黑色且其两个孩子都为黑色时,将兄弟节点变成红色,将node节点升级为父节点
                    w.color = false;
                    node = node.parent;
                } else if (w.right.color) {//当兄弟节点为黑色且其左孩子为红色、其右孩子为黑色时,将其左孩子变成黑色、兄弟节点变成红色,右旋兄弟节点,更新兄弟节点
                    w.left.color = true;
                    w.color = false;
                    rightTotate(w);
                    w = node.parent.right;
                } else {//当兄弟节点为黑色且其右孩子为红色时,将父节点的颜色赋给兄弟节点,父节点变成黑色,兄弟节点的右孩子变成黑色,左旋父节点
                    w.color = node.parent.color;
                    node.parent.color = true;
                    w.right.color = true;
                    leftTotate(node.parent);
                    // 将根节点赋给node
                    if (root.parent != null) {
                        root = root.parent;
                    }
                    node = root;
                }
            } else {// 如果node节点为父节点的右孩子
                // 定义w存兄弟节点
                Node w = node.parent.left;
                // 当兄弟节点为红色时,将兄弟节点变成黑色,父节点变成红色,右旋父节点,更新兄弟节点
                if (!w.color) {
                    w.color = true;
                    node.parent.color = false;
                    rightTotate(node.parent);
                    w = node.parent.left;
                } else if (w.left.color && w.right.color) {//当兄弟节点为黑色且其两个孩子都为黑色时,将兄弟节点变成红色,将node节点升级为父节点
                    w.color = false;
                    node = node.parent;
                } else if (w.left.color) {//当兄弟节点为黑色且其左孩子为黑色、其右孩子为红色时,将其右孩子变成黑色、兄弟节点变成红色,左旋兄弟节点,更新兄弟节点
                    w.right.color = true;
                    w.color = false;
                    leftTotate(w);
                    w = node.parent.left;
                } else {//当兄弟节点为黑色且其左孩子为红色时,将父节点的颜色赋给兄弟节点,父节点变成黑色,兄弟节点的左孩子变成黑色,右旋父节点
                    w.color = node.parent.color;
                    node.parent.color = true;
                    w.left.color = true;
                    rightTotate(node.parent);
                    // 将根节点赋给node
                    if (root.parent != null) {
                        root = root.parent;
                    }
                    node = root;
                }
            }
        }
        // 将node节点变成黑色
        node.color = true;
    }

    public static void main(String[] args) {
        int[] arr = { 21, 3, 6, 7, 12, 25, 17, 8, 15 };
        RBTree rb = new RBTree(21);
        for (int i = 1; i < arr.length; i++) {
            rb.RBTreeInsert(arr[i]);
        }
        rb.inOrderTreeWalk(root);
        rb.RBTreeDelete(rb.treeSearch(root, 21));
        System.out.println();
        rb.inOrderTreeWalk(root);
    }

}

原文地址:https://www.cnblogs.com/lirun/p/9886505.html

时间: 2024-08-11 09:48:45

二叉树与红黑树的java实现的相关文章

二叉树之红黑树(RBTree)

详解以后再补充... 红黑树和AVL树6层模式下的最少结点数 通过图可以看到红黑树可以实现更少的结点,反过来说就是同样的结点数红黑树最大数高会超过AVL树 https://www.cs.usfca.edu/~galles/visualization/Algorithms.html这个网站可以测试动态效果,下图就是截图于此 红黑树插入删除步骤 输出 代码 其余代码:https://github.com/Duacai/Data-Structure-and-Algorithms/tree/master

堆,二叉树,红黑树,B数。

堆的概念: 堆中某个节点的值总是不大于或不小于其父节点的值: 堆总是一棵完全二叉树. 以百度的一个面试题为例: 序列{9,12,17,30,50,20,60,65,4,19}构造为堆后,堆所对应的的中序遍历序列可能为 65,12,30,50,9,19,20,4,,17,60 65,12,30,9,50,19,4,20,17,60 65,9,30,12,19,50,4,20,17,60 65,12,9,30,50,4,20,9,17,60 一.序列构造成堆: 1:1~9都是,从上到下,从左到右堆积

HashMap、ConcurrentHashMap、二叉树、红黑树

HashMap: 数组+链表结构. HashMap是一个用于存储Key-Value键值对的集合,初始化长度16 每次拓展长度必须是2的幂 (为了服务于key映射到index的Hash算法index =  HashCode(Key) &  (Length - 1)).每一个键值对也叫做Entry.这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干,每个初始值都是null.当进行put操作时,为了使得数据均匀分布会对key进行hash操作再和 HashMap长度进行与

java中treemap和treeset实现(红黑树)

TreeMap 的实现就是红黑树数据结构,也就说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索指定节点. TreeSet 和 TreeMap 的关系 为了让大家了解 TreeMap 和 TreeSet 之间的关系,下面先看 TreeSet 类的部分源代码: public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializab

Java实现红黑树

转自:http://www.cnblogs.com/skywang12345/p/3624343.html 红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键值,小于等于右孩子的键值.除了具备该特性之外,红黑树还包括许多额外的信息. 红黑树的每个节点上都有存储位表示节点的颜色,颜色是红(Red)或黑(Black).红黑树的特性:(1) 每个节点或者

树/二叉树(哈夫曼树/红黑树)笔记

1.树是一种常用数据结构,它是非线性结构. 2.树中任一普通节点可以有0或者多个子节点,但只能有一个父节点. 根节点没有父节点, 叶子节点没有子节点. 3.二叉树: 1)每个节点最多只能有两个子树的有序树 2)左边的子树称为左子树 3)右边的子树成为右子树 4)一棵深度为k的二叉树,如果它包含了(2^k-1)个节点,就把这棵二叉树称为满二叉树 4.满二叉树的特点: 1)每一层上的节点数都是最大节点数,即各层为1,2,4,8,16 .... (2^k-1) 2)一棵有n个节点的二叉树,按满二叉树的

9.6-全栈Java笔记:二叉树和红黑二叉树

二叉树的定义 二叉树是树形结构的一个重要类型. 许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要. 二叉树(BinaryTree)由一个结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成.下图中展现了五种不同基本形态的二叉树. (a) 为空树 (b) 为仅有一个结点的二叉树 (c) 是仅有左子树而右子树为空的二叉树 (d) 是仅有右子树而左子树为空的二叉树 (e) 是左.右子树均非

java数据结构和算法06(红黑树)

这一篇我们来看看红黑树,首先说一下我啃红黑树的一点想法,刚开始的时候比较蒙,what?这到底是什么鬼啊?还有这种操作?有好久的时间我都缓不过来,直到我玩了两把王者之后回头一看,好像有点儿意思,所以有的时候碰到一个问题困扰了很久可以先让自己的头脑放松一下,哈哈! 不瞎扯咳,开始今天的正题: 前提:看红黑树之前一定要先会搜索二叉树 1.红黑树的概念 红黑树到底是个什么鬼呢?我最开始也在想这个问题,你说前面的搜索二叉树多牛,各种操作效率也不错,用起来很爽啊,为什么突然又冒出来了红黑树啊? 确实,搜索二

Java数据结构——红黑树

红黑树介绍红黑树(Red-Black Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键值,小于等于右孩子的键值.红黑树的每个节点上都有存储位表示节点的颜色,颜色是红(Red)或黑(Black).红黑树的特性: 每个节点或者是黑色,或者是红色. 根节点是黑色. 每个叶子节点是黑色. (注意:这里叶子节点,是指为空的叶子节点) 如果一个节点是红色的,则它的子节点必须是黑色的. 从一个节点到该节点的子孙节点的所有路