Java数据结构--红黑树
2017-12-28 21:32
295 查看
DEMO:
https://github.com/zhaopingfu/MDataStruct/blob/master/src/com/pf/%E6%A0%91/RedBlackBintrayTree.java
一些资源:
https://github.com/zhaopingfu/MDataStruct/tree/master/resources/%E6%A0%91/%E7%BA%A2%E9%BB%91%E6%A0%91
2、根节点是黑的。
3、每个叶节点,即空节点(NIL)是黑的。
4、如果一个节点是红的,那么它的俩个儿子都是黑的。
5、对每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点。
https://github.com/zhaopingfu/MDataStruct/blob/master/src/com/pf/%E6%A0%91/RedBlackBintrayTree.java
一些资源:
https://github.com/zhaopingfu/MDataStruct/tree/master/resources/%E6%A0%91/%E7%BA%A2%E9%BB%91%E6%A0%91
红黑树的性质
1、每个节点要么是红的,要么是黑的。2、根节点是黑的。
3、每个叶节点,即空节点(NIL)是黑的。
4、如果一个节点是红的,那么它的俩个儿子都是黑的。
5、对每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点。
插入节点
插入节点:先按照二叉排序树的方式插入一个节点,再查找最小不平衡子树,以最小不平衡子树进行下面的操作 删除节点:先进行二叉排序树的删除操作,然后已替换节点作为当前节点进行后面的平衡操作 /** * @author zhaopf * @version 1.0 * @QQ: 1308108803 * @date 2017年12月26日 * 红黑树 */ public class RedBlackBintrayTree<E extends Comparable<E>> { /** * 根节点 */ private Node<E> root; /** * 树的节点 */ private int size; /** * 红色 */ private static final boolean RED = false; /** * 黑色 */ private static final boolean BLACK = true; /** * 添加一个元素 * * @param element * @return */ public boolean put(E element) { if (element == null) { return false; } Node<E> t = root; // 插入的是根节点,直接将节点涂黑 if (t == null) { root = new Node<>(element, null); size++; return true; } // 开始添加元素 Node<E> parent = null; Comparable<? super E> e = element; int compare; // 查找父节点 do { parent = t; compare = e.compareTo(t.getElement()); if (compare > 0) { t = t.getRight(); } else if (compare < 0) { t = t.getLeft(); } else { return false; } } while (t != null); // 添加到父节点上 Node<E> newNode = new Node<>(element, parent); compare = newNode.element.compareTo(parent.getElement()); if (compare > 0) { parent.right = newNode; } else if (compare < 0) { parent.left = newNode; } // 检查颜色 fixAfterInsertion(newNode); size++; return true; } /** * 添加节点调整颜色 * * @param x */ private void fixAfterInsertion(Node<E> x) { if (x == null) { return; } x.color = RED; // 如果插入节点的父节点是黑色,不做任何处理 // 如果插入节点的父节点 while (x != null && x != root && x.getParent().getColor() == RED) { // 父节点是祖父节点的左孩子 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { Node<E> y = rightOf(parentOf(parentOf(x))); // 祖父节点的另一个节点是红色 // 将当前节点的父节点和叔叔节点涂黑,祖父节点涂红,把当前节点指向祖父节点,从新的当前节点开始算法 if (colorOf(y) == RED) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { // 叔叔节点是黑色 // 当前节点是其父节点的右孩子,当前节点的父节点做为新的当前节点,以新当前节点为支点左旋 if (x == rightOf(parentOf(x))) { x = parentOf(x); leftRotate(x); } // 当前节点是其父节点的左孩子,父节点变为黑色,祖父节点变红色,再祖父节点为支点进行右旋 setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); rightRotate(parentOf(parentOf(x))); } } else { // 和上面的情况一样,将左全部变成右 Node<E> y = leftOf(parentOf(parentOf(x))); if (colorOf(y) == RED) { setColor(parentOf(x), BLACK); setColor(y, BLACK); setColor(parentOf(parentOf(x)), RED); x = parentOf(parentOf(x)); } else { if (x == leftOf(parentOf(x))) { x = parentOf(x); rightRotate(x); } setColor(parentOf(x), BLACK); setColor(parentOf(parentOf(x)), RED); leftRotate(parentOf(parentOf(x))); } } } root.color = BLACK; } /** * 获取节点 * * @param data * @return */ public Node<E> get(E data) { if (data == null) { return null; } Comparable<? super E> e = data; Node<E> x = root; while (x != null) { int cmp = e.compareTo(x.getElement()); if (cmp > 0) { x = x.getRight(); } else if (cmp < 0) { x = x.getLeft(); } else { return x; } } return null; } /** * 删除节点 * * @param e * @return */ public boolean remove(E e) { Node<E> node = get(e); if (node == null) { return false; } // 有两个孩子,右孩子的最左边的孩子为继承人 if (node.getLeft() != null && node.getRight() != null) { Node<E> p = node.getRight(); while (p.getLeft() != null) { p = p.getLeft(); } // 把node指针上的数据改变 node.setElement(p.getElement()); // 将node指针指向 p 指针,到这里实际上数据已经不在了,接下来要做的只是把node和p之间的关系断开 node = p; } Node<E> replacement = (node.getLeft() != null ? node.getLeft() : node.getRight()); // 至少有一个孩子 if (replacement != null) { replacement.setParent(node.getParent()); if (node.getParent() == null) { root = replacement; } else if (node == node.getParent().getLeft()) { node.getParent().setLeft(replacement); } else if (node == node.getParent().getRight()) { node.getParent().setRight(replacement); } node.setLeft(null); node.setRight(null); node.setParent(null); // 如果是黑色,要调整颜色 if (node.getColor() == BLACK) { fixAfterDeletion(replacement); } } // 没有孩子且父节点为空 else if (node.parent == null) { root = null; } // 没有孩子有父节点 else { // 如果是删除黑色,需要调整树 if (node.getColor() == BLACK) { fixAfterDeletion(node); } if (node.getParent() != null) { if (node == node.getParent().getLeft()) { node.getParent().setLeft(null); } else if (node == node.getParent().getRight()) { node.getParent().setRight(null); } node.setParent(null); } } size--; return true; } /** * 删除节点之后修改树 * * @param x */ private void fixAfterDeletion(Node<E> x) { if (x == null) { return; } while (x != null && x != root && colorOf(x) == BLACK) { if (x == leftOf(parentOf(x))) { // 兄弟节点 Node<E> y = rightOf(parentOf(x)); // 兄弟节点为红色 if (colorOf(y) == RED) { setColor(y, BLACK); setColor(parentOf(x), RED); leftRotate(parentOf(x)); y = rightOf(parentOf(x)); } // 如果兄弟的两个孩子都是黑色 if (colorOf(leftOf(y)) == BLACK && colorOf(rightOf(y)) == BLACK) { setColor(y, RED); x = parentOf(x); } else { // 兄弟的右孩子为黑色 if (colorOf(rightOf(y)) == BLACK) { setColor(leftOf(y), BLACK); setColor(y, RED); rightRotate(y); y = rightOf(parentOf(x)); } setColor(y, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(rightOf(y), BLACK); leftRotate(parentOf(x)); x = root; } } else { // 兄弟节点 Node<E> y = leftOf(parentOf(x)); // 兄弟节点为红色 if (colorOf(y) == RED) { setColor(y, BLACK); setColor(parentOf(x), RED); rightRotate(parentOf(x)); y = leftOf(parentOf(x)); } // 如果兄弟的两个孩子都是黑色 if (colorOf(leftOf(y)) == BLACK && colorOf(rightOf(y)) == BLACK) c9c0 { setColor(y, RED); x = parentOf(x); } else { // 兄弟的左孩子为黑色 if (colorOf(leftOf(y)) == BLACK) { setColor(rightOf(y), BLACK); setColor(y, RED); leftRotate(y); y = leftOf(parentOf(x)); } setColor(y, colorOf(parentOf(x))); setColor(parentOf(x), BLACK); setColor(leftOf(y), BLACK); rightRotate(parentOf(x)); x = root; } } } setColor(x, BLACK); } /** * 中序遍历节点 * * @return */ public List<Node<E>> midSelectTree() { List<Node<E>> result = new ArrayList<>(size); Node<E> temp = root; if (temp == null) { return result; } Stack<Node<E>> stack = new Stack<>(); // 添加根节点 stack.add(temp); Set<Node<E>> set = new HashSet<>(size); while (!stack.isEmpty()) { Node<E> t = stack.pop(); if (t.getLeft() != null && !set.contains(t.getLeft())) { if (t.getRight() != null) { stack.push(t.getRight()); } stack.push(t); stack.push(t.getLeft()); } else { set.add(t); result.add(t); if (t.getRight() != null && !stack.contains(t.getRight())) { stack.push(t.getRight()); } } } return result; } private Node<E> parentOf(Node<E> node) { return (node == null ? null : node.getParent()); } private Node<E> leftOf(Node<E> node) { return (node == null ? null : node.getLeft()); } private Node<E> rightOf(Node<E> node) { return (node == null ? null : node.getRight()); } private boolean colorOf(Node<E> node) { return (node == null ? BLACK : node.getColor()); } private void setColor(Node<E> node, boolean color) { if (node != null) { node.setColor(color); } } /** * 左旋 * * @param x 要旋转的节点 */ private void leftRotate(Node<E> x) { if (x == null || x.getRight() == null) { return; } Node<E> y = x.right; // step 1 x.right = y.left; if (y.left != null) { y.left.parent = x; } // step 2 if (x.parent == null) { root = y; } else if (x.parent.left == x) { x.parent.left = y; } else if (x.parent.right == x) { x.parent.right = y; } y.parent = x.parent; // step 3 y.left = x; x.parent = y; } /** * 右旋 * * @param y 要旋转的节点 */ private void rightRotate(Node<E> y) { if (y == null || y.getLeft() == null) { return; } Node<E> x = y.left; // step 1 y.left = x.right; if (x.right != null) { x.right.parent = y; } // step 2 if (y.parent == null) { root = x; } else if (y.parent.left == y) { y.parent.left = x; } else if (y.parent.right == y) { y.parent.right = x; } x.parent = y.parent; // step 3 x.right = y; y.parent = x; } public int getSize() { return size; } public Node<E> getRoot() { return root; } /** * 节点 * * @param <E> 实现了Comparable接口 */ public class Node<E extends Comparable<E>> { /** * 数据 */ private E element; /** * 左子树 */ private Node<E> left; /** * 右子树 */ private Node<E> right; /** * 父节点 */ private Node<E> parent; /** * 这里默认黑色 */ private boolean color = BLACK; public Node(E element, Node<E> parent) { this.element = element; this.parent = parent; } public E getElement() { return element; } public void setElement(E element) { this.element = element; } public Node<E> getLeft() { return left; } public void setLeft(Node<E> left) { this.left = left; } public Node<E> getRight() { return right; } public void setRight(Node<E> right) { this.right = right; } public Node<E> getParent() { return parent; } public void setParent(Node<E> parent) { this.parent = parent; } public boolean getColor() { return color; } public void setColor(boolean color) { this.color = color; } } }
相关文章推荐
- 数据结构 - 红黑树(Red Black Tree)删除详解与实现(Java)
- Java数据结构和算法(十一)——红黑树
- 数据结构:红黑树java实现
- 数据结构 JAVA描述(十六) 动态查找 B-树 B+树 红黑树
- 数据结构--红黑树(java)
- JAVA中的数据结构 - 真正的去理解红黑树
- Java数据结构----树--红黑树
- Java源码集合类TreeMap学习1——数据结构5红黑树
- Java数据结构之红黑树的真正理解
- JAVA中的数据结构 - 真正的去理解红黑树
- Java数据结构和算法(十一)——红黑树
- 【JAVA数据结构】 简单链表的实现
- 2.Java数据结构原理解析-List系列
- java数据结构——5栈(Stack)
- java数据结构之循环双链表
- 利用java实现数据结构中常用的插入排序和快速排序算法
- 数据结构--图的理解:深度优先和广度优先遍历及其 Java 实现
- 一步步学习数据结构和算法之冒泡排序效率分析及java实现
- 浅谈算法和数据结构: 平衡查找树之红黑树
- 【数据结构】之二叉树的java实现