您的位置:首页 > 理论基础 > 数据结构算法

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

红黑树的性质

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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 数据结构