算法导论读书笔记(15) - 红黑树的具体实现

算法导论读书笔记(15) - 红黑树的具体实现

目录

  • 红黑树的简单Java实现

红黑树的简单Java实现

/**
* 红黑树
*
* 部分代码参考自TreeMap源码
*/
public class RedBlackTree<T> {
protected TreeNode<T> root = null;
private final Comparator<? super T> comparator;
private int size = 0;
private static final boolean RED = false;
private static final boolean BLACK = true;

public RedBlackTree() {
this.comparator = null;
}

public RedBlackTree(Comparator<? super T> comparator) {
this.comparator = comparator;
}

public void insert(T key) {
TreeNode<T> x = root;
TreeNode<T> y = null;
TreeNode<T> z = new TreeNode<T>(key, null);
int cmp;
if (x == null) {
root = z;
size = 1;
return;
}
while (x != null) {
y = x;
cmp = compareKey(z.key, x.key);
if (cmp < 0)
x = x.left;
else
x = x.right;
}
z.parent = y;
cmp = compareKey(z.key, y.key);
if (cmp < 0)
y.left = z;
else
y.right = z;
z.left = z.right = null;
fixAfterInsertion(z);
size++;
}

public T remove(T key) {
TreeNode<T> p = find(key);
if (p == null)
return null;
T oldValue = p.key;
deleteNode(p);
return oldValue;
}

public boolean isEmpty() {
return size() == 0;
}

public int size() {
return size;
}

public TreeNode<T> firstNode() {
return getFirstNode(root);
}

public TreeNode<T> lastNode() {
return getLastNode(root);
}

public TreeNode<T> find(T t) {
TreeNode<T> p = root;
while (p != null) {
int cmp = compareKey(t, p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}

public Set<TreeNode<T>> nodeSet() {
return new NodeSet();
}

public static final class TreeNode<T> {
T key;
TreeNode<T> left = null;
TreeNode<T> right = null;
TreeNode<T> parent;
boolean color = BLACK;

TreeNode(T key, TreeNode<T> parent) {
this.key = key;
this.parent = parent;
}

public T getKey() {
return key;
}

public boolean equals(Object o) {
if (!(o instanceof TreeNode))
return false;
TreeNode<?> e = (TreeNode<?>) o;
return keyEquals(key, e.getKey());
}

public String toString() {
return "[" + key + " : " + (color ? "BLACK" : "RED") + "]";
}
}

private static <T> TreeNode<T> successor(TreeNode<T> t) {
if (t == null)
return t;
else if (t.right != null)
return getFirstNode(t.right);
else {
TreeNode<T> p = t.parent;
TreeNode<T> ch = t;
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}

private static <T> TreeNode<T> predecessor(TreeNode<T> t) {
if (t == null)
return t;
else if (t.left != null)
return getLastNode(t.left);
else {
TreeNode<T> p = t.parent;
TreeNode<T> ch = t;
while (p != null && ch == p.left) {
ch = p;
p = p.parent;
}
return p;
}
}

private static <T> TreeNode<T> getFirstNode(TreeNode<T> t) {
TreeNode<T> p = t;
if (p != null)
while (p.left != null)
p = p.left;
return p;
}

private static <T> TreeNode<T> getLastNode(TreeNode<T> t) {
TreeNode<T> p = t;
if (p != null)
while (p.right != null)
p = p.right;
return p;
}

private static boolean keyEquals(Object o1, Object o2) {
return (o1 == null ? o2 == null : o1.equals(o2));
}

private int compareKey(T key1, T key2) {
int cmp;
if (comparator != null)
cmp = comparator.compare(key1, key2);
else {
if (key1 == null || key2 == null)
throw new NullPointerException();
Comparable<? super T> k = (Comparable<? super T>) key1;
cmp = k.compareTo(key2);
}
return cmp;
}

private void rotateLeft(TreeNode<T> p) {
if (p != null) {
TreeNode<T> r = p.right;
p.right = r.left;
if (r.left != null)
r.left.parent = p;
r.parent = p.parent;
if (p.parent == null)
root = r;
else if (p.parent.left == p)
p.parent.left = r;
else
p.parent.right = r;
r.left = p;
p.parent = r;
}
}

private void rotateRight(TreeNode<T> p) {
if (p != null) {
TreeNode<T> l = p.left;
p.left = l.right;
if (l.right != null)
l.right.parent = p;
l.parent = p.parent;
if (p.parent == null)
root = l;
else if (p.parent.right == p)
p.parent.right = l;
else
p.parent.left = l;
l.right = p;
p.parent = l;
}
}

private void fixAfterInsertion(TreeNode<T> x) {
x.color = RED;
while (x != null && x != root && x.parent.color == RED) {
if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
TreeNode<T> 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);
rotateLeft(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateRight(parentOf(parentOf(x)));
}
} else {
TreeNode<T> 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);
rotateRight(x);
}
setColor(parentOf(x), BLACK);
setColor(parentOf(parentOf(x)), RED);
rotateLeft(parentOf(parentOf(x)));
}
}
}
root.color = BLACK;
}

private void deleteNode(TreeNode<T> p) {
size--;
TreeNode<T> y = p;
TreeNode<T> x;
boolean y_original_color = colorOf(y);
if (leftOf(p) == null) {
x = rightOf(p);
transplant(p, rightOf(p));
} else if (rightOf(p) == null) {
x = leftOf(p);
transplant(p, leftOf(p));
} else {
y = getFirstNode(rightOf(p));
y_original_color = colorOf(y);
x = rightOf(y);
if (parentOf(y) == p)
x.parent = y;
else {
transplant(y, rightOf(y));
y.right = rightOf(p);
y.right.parent = y;
}
transplant(p, y);
y.left = leftOf(p);
y.left.parent = y;
y.color = colorOf(p);
}
if (y_original_color == BLACK)
fixAfterDeletion(x);
}

private void fixAfterDeletion(TreeNode<T> x) {
while (x != root && colorOf(x) == BLACK) {
if (x == leftOf(parentOf(x))) {
TreeNode<T> sib = rightOf(parentOf(x));

if (colorOf(sib) == RED) {
setColor(sib, BLACK);
setColor(parentOf(x), RED);
rotateLeft(parentOf(x));
sib = rightOf(parentOf(x));
}

if (colorOf(leftOf(sib)) == BLACK
&& colorOf(rightOf(sib)) == BLACK) {
setColor(sib, RED);
x = parentOf(x);
} else {
if (colorOf(rightOf(sib)) == BLACK) {
setColor(leftOf(sib), BLACK);
setColor(sib, RED);
rotateRight(sib);
sib = rightOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), BLACK);
setColor(rightOf(sib), BLACK);
rotateLeft(parentOf(x));
x = root;
}
} else { // symmetric
TreeNode<T> sib = leftOf(parentOf(x));

if (colorOf(sib) == RED) {
setColor(sib, BLACK);
setColor(parentOf(x), RED);
rotateRight(parentOf(x));
sib = leftOf(parentOf(x));
}

if (colorOf(rightOf(sib)) == BLACK
&& colorOf(leftOf(sib)) == BLACK) {
setColor(sib, RED);
x = parentOf(x);
} else {
if (colorOf(leftOf(sib)) == BLACK) {
setColor(rightOf(sib), BLACK);
setColor(sib, RED);
rotateLeft(sib);
sib = leftOf(parentOf(x));
}
setColor(sib, colorOf(parentOf(x)));
setColor(parentOf(x), BLACK);
setColor(leftOf(sib), BLACK);
rotateRight(parentOf(x));
x = root;
}
}
}

setColor(x, BLACK);
}

private void transplant(TreeNode<T> u, TreeNode<T> v) {
if (parentOf(u) == null)
root = v;
else if (u == leftOf(parentOf(u)))
u.parent.left = v;
else
u.parent.right = v;
if (v != null)
v.parent = u.parent;
}

/**
* 树的平衡操作
*
* 树的实现没有使用哨兵元素,而是使用下列方法处理null的情况
*/
private static <T> boolean colorOf(TreeNode<T> p) {
return (p == null ? BLACK : p.color);
}

private static <T> TreeNode<T> parentOf(TreeNode<T> p) {
return (p == null ? null : p.parent);
}

private static <T> void setColor(TreeNode<T> p, boolean c) {
if (p != null)
p.color = c;
}

private static <T> TreeNode<T> leftOf(TreeNode<T> p) {
return (p == null) ? null : p.left;
}

private static <T> TreeNode<T> rightOf(TreeNode<T> p) {
return (p == null) ? null : p.right;
}

final class NodeSet extends AbstractSet<TreeNode<T>> {

public Iterator<TreeNode<T>> iterator() {
return new NodeIterator(firstNode());
}

public int size() {
return RedBlackTree.this.size();
}
}

/**
* 红黑树的迭代器
*/
final class NodeIterator extends PrivateNodeIterator<TreeNode<T>> {
NodeIterator(TreeNode<T> first) {
super(first);
}

public TreeNode<T> next() {
return nextNode();
}

public void remove() {
}
}

abstract class PrivateNodeIterator<E> implements Iterator<E> {
TreeNode<T> next;

PrivateNodeIterator(TreeNode<T> first) {
next = first;
}

public boolean hasNext() {
return next != null;
}

final TreeNode<T> nextNode() {
TreeNode<T> e = next;
if (e == null)
throw new NoSuchElementException();
next = successor(e);
return e;
}
}
}

算法导论读书笔记(15) - 红黑树的具体实现,布布扣,bubuko.com

时间: 2024-12-21 10:39:54

算法导论读书笔记(15) - 红黑树的具体实现的相关文章

算法导论读书笔记(13)

算法导论读书笔记(13) 目录 红黑树 旋转 插入 情况1 : z 的叔父结点 y 是红色的 情况2 : z 的叔父结点 y 是黑色的,而且 z 是右孩子 情况3 : z 的叔父结点 y 是黑色的,而且 z 是左孩子 删除 情况1 : x 的兄弟 w 是红色的 情况2 : x 的兄弟 w 是黑色的,且 w 的两个孩子都是黑色的 情况3 : x 的兄弟 w 是黑色的, w 的左孩子是红色的,右孩子是黑色的 情况4 : x 的兄弟 w 是黑色的,且 w 的右孩子是红色的 红黑树 红黑树 是一种二叉查

算法导论读书笔记(16)

算法导论读书笔记(16) 目录 动态顺序统计 检索具有给定排序的元素 确定一个元素的秩 区间树 步骤1:基础数据结构 步骤2:附加信息 步骤3:维护信息 步骤4:设计新操作 动态顺序统计 之前介绍过 顺序统计 的概念.在一个无序的集合中,任意的顺序统计量都可以在 O ( n )时间内找到.而这里我们将介绍如何在 O ( lg n )时间内确定任意的顺序统计量. 下图显示的是一种支持快速顺序统计量操作的数据结构.一棵 顺序统计树 T 通过在红黑树的每个结点中存入附加信息而成.在一个结点 x 内,增

算法导论读书笔记(18)

算法导论读书笔记(18) 目录 最长公共子序列 步骤1:描述最长公共子序列的特征 步骤2:一个递归解 步骤3:计算LCS的长度 步骤4:构造LCS LCS问题的简单Java实现 最长公共子序列 某给定序列的子序列,就是将给定序列中零个或多个元素去掉后得到的结果.其形式化定义如下:给定一个序列 X = < x1 , x2 , - , xm >,另一个序列 Z = < z1 , z2 , - , zk >,如果 Z 满足如下条件则称 Z 为 X 的 子序列 (subsequence),

算法导论读书笔记之钢条切割问题

算法导论读书笔记之钢条切割问题 巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo) 给定一段长度为n英寸的钢条和一个价格表 pi (i=1,2, -,n),求切割钢条的方案,使得销售收益rn最大.注意,如果长度为n英寸的钢条价格pn足够大,最优解可能就是完全不需要切割. 若钢条的长度为i,则钢条的价格为Pi,如何对给定长度的钢条进行切割能得到最大收益? 长度i   1   2    3   4     5      6     7     8  

算法导论 第13章 红黑树

二叉查找树的基本操作包括搜索.插入.删除.取最大和最小值等都能够在O(h)时间复杂度内实现,因此能在期望时间O(lgn)下实现,但是二叉查找树的平衡性在这些操作中并没有得到维护,因此其高度可能会变得很高,当其高度较高时,而二叉查找树的性能就未必比链表好了,所以二叉查找树的集合操作是期望时间O(lgn),最坏情况下为O(n). 红黑树也是一种二叉查找树,它拥有二叉查找树的性质,同时红黑树还有其它一些特殊性质,这使得红黑树的动态集合基本操作在最坏情况下也为O(lgn),红黑树通过给节点增加颜色和其它

算法导论读书笔记(17)

算法导论读书笔记(17) 目录 动态规划概述 钢条切割 自顶向下的递归实现 使用动态规划解决钢条切割问题 子问题图 重构解 钢条切割问题的简单Java实现 动态规划概述 和分治法一样, 动态规划 (dynamic programming)是通过组合子问题的解而解决整个问题的.分治法是将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题并不独立的情况,即各子问题包含公共的子子问题.在这种情况下,分治法会重复地求解公共的子子问题.而动态

算法导论读书笔记(14) - 二叉查找树的具体实现

算法导论读书笔记(14) - 二叉查找树的具体实现 目录 二叉查找树的简单Java实现 二叉查找树的简单Java实现 /** * 二叉查找树 * 部分代码参考自TreeMap的源码 */ public class BinarySearchTree<T> { protected TreeNode<T> root = null; private final Comparator<? super T> comparator; private int size = 0; pub

算法导论第十三章 红黑树

写在前面:这一章真的把我害惨了,之前至少尝试看过3遍,每次看之前都下定决定一定要把它拿下,可是由于内容较多,深度够深,以致于每次要不是中途有什么事放弃了就跳过了,要不是花时间太多仍然不能理解而放弃.这次总算挺过来了,前后零零散散的时间加起来差不多也有两天时间.这次能坚持下来并攻克,我想大概有这么几个原因吧:第一是之前下定的决心要写一个最新版<算法导论>的读书笔记,之前几章都坚持写了,不能让这个成为拦路虎,即使再难再花时间都要弄懂:第二是通过前面几章的动手实践,发现自己的理解能力.动手能力都进步

算法导论读书笔记-第十四章-数据结构的扩张

算法导论第14章 数据结构的扩张 一些工程应用需要的只是标准数据结构, 但也有许多其他的应用需要对现有数据结构进行少许的创新和改造, 但是只在很少情况下需要创造出全新类型的数据结构, 更经常的是通过存储额外信息的方法来扩张一种标准的数据结构, 然后对这种数据结构编写新的操作来支持所需要的应用. 但是对数据结构的扩张并不总是简单直接的, 因为新的信息必须要能被该数据结构上的常规操作更新和维护. 14.1 动态顺序统计 顺序统计树(order-static tree) : 在红黑树的基础上, 在每个