▶ 书中第三章部分程序,加上自己补充的代码,红黑树

● 红黑树,大部分方法与注释与二叉树相同

 package package01;

 import java.util.NoSuchElementException;
import edu.princeton.cs.algs4.Queue;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut; public class class01<Key extends Comparable<Key>, Value>
{
private static final boolean RED = true;
private static final boolean BLACK = false; private class Node
{
private Key key;
private Value val;
private Node left, right;
private boolean color; // 指向该节点的连接的颜色
private int size; public Node(Key key, Value val, boolean color, int size)
{
this.key = key;
this.val = val;
this.color = color;
this.size = size;
}
} private Node root; public class01() {} private boolean isRed(Node x)
{
if (x == null)
return false;
return x.color == RED;
} public int size()
{
return size(root);
} private int size(Node x)
{
if (x == null)
return 0;
return x.size;
} public boolean isEmpty()
{
return size() == 0; //return root == null;
} public Value get(Key key) // 查找
{
if (key == null)
throw new IllegalArgumentException("\n<get> key == null.\n");
return getKernel(root, key);
} private Value getKernel(Node x, Key key)// 查找内核,使用了非递归实现
{
for (int cmp = key.compareTo(x.key); x != null; cmp = key.compareTo(x.key))
{
if (cmp < 0)
x = x.left;
else if (cmp > 0)
x = x.right;
else
return x.val;
}
return null;
} public boolean contains(Key key) // 判断 key 是否在树中
{
if (key == null)
throw new IllegalArgumentException("\n<contains> key == null.\n");
return get(key) != null;
} public void put(Key key, Value val) // 插入
{
if (key == null)
throw new IllegalArgumentException("\n<put> key == null.\n");
if (val == null)
delete(key);
else
{
root = putKernel(root, key, val);
root.color = BLACK;
}
// assert check();
} private Node putKernel(Node x, Key key, Value val)
{
if (x == null)
return new Node(key, val, RED, 1);
int cmp = key.compareTo(x.key);
if (cmp < 0)
x.left = putKernel(x.left, key, val);
else if (cmp > 0)
x.right = putKernel(x.right, key, val);
else
x.val = val;
if (isRed(x.right) && !isRed(x.left))
x = rotateLeft(x);
if (isRed(x.left) && isRed(x.left.left))
x = rotateRight(x);
if (isRed(x.left) && isRed(x.right))
flipColors(x);
x.size = 1 + size(x.left) + size(x.right);
return x;
} public void deleteMin()
{
if (isEmpty())
throw new NoSuchElementException("\n<deleteMin> underflow.\n");
if (!isRed(root.left) && !isRed(root.right))
root.color = RED;
root = deleteMinKernel(root);
if (!isEmpty())
root.color = BLACK;
// assert check();
} private Node deleteMinKernel(Node x)
{
if (x.left == null)
return null;
if (!isRed(x.left) && !isRed(x.left.left))
x = moveRedLeft(x);
x.left = deleteMinKernel(x.left);
return balance(x);
} public void deleteMax()
{
if (isEmpty())
throw new NoSuchElementException("\n<deleteMax> underflow.\n");
if (!isRed(root.left) && !isRed(root.right))
root.color = RED;
root = deleteMaxKernel(root);
if (!isEmpty())
root.color = BLACK;
// assert check();
} private Node deleteMaxKernel(Node x)
{
if (isRed(x.left))
x = rotateRight(x);
if (x.right == null)
return null;
if (!isRed(x.right) && !isRed(x.right.left))
x = moveRedRight(x);
x.right = deleteMaxKernel(x.right);
return balance(x);
} public void delete(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<delete> key == null.\n");
if (!contains(key))
return;
if (!isRed(root.left) && !isRed(root.right))
root.color = RED;
root = deleteKernel(root, key);
if (!isEmpty())
root.color = BLACK;
// assert check();
} private Node deleteKernel(Node x, Key key)
{
if (key.compareTo(x.key) < 0)
{
if (!isRed(x.left) && !isRed(x.left.left))
x = moveRedLeft(x);
x.left = deleteKernel(x.left, key);
}
else
{
if (isRed(x.left))
x = rotateRight(x);
if (key.compareTo(x.key) == 0 && (x.right == null))
return null;
if (!isRed(x.right) && !isRed(x.right.left))
x = moveRedRight(x);
if (key.compareTo(x.key) == 0)
{
Node t = minKernel(x.right);
x.key = t.key;
x.val = t.val;
// x.val = get(x.right, min(x.right).key);
// x.key = min(x.right).key;
x.right = deleteMinKernel(x.right);
}
else x.right = deleteKernel(x.right, key);
}
return balance(x);
} private Node rotateRight(Node x) // 右旋转
{
Node t = x.left;
x.left = t.right;
t.right = x;
t.color = t.right.color;
t.right.color = RED;
t.size = x.size;
x.size = 1 + size(x.left) + size(x.right);
return t;
} private Node rotateLeft(Node x) // 左旋转
{
Node t = x.right;
x.right = t.left;
t.left = x;
t.color = t.left.color;
t.left.color = RED;
t.size = x.size;
x.size = 1 + size(x.left) + size(x.right);
return t;
} private void flipColors(Node x) // 改变节点及其子节点的颜色
{
// assert (x != null) && (x.left != null) && (x.right != null);
// assert (!isRed(x) && isRed(x.left) && isRed(x.right)) || (isRed(x) && !isRed(x.left) && !isRed(x.right));
x.color = !x.color;
x.left.color = !x.left.color;
x.right.color = !x.right.color;
} private Node moveRedLeft(Node x) // x 红而 x.left 和 x.left.left 都是黑的,调整使得两个黑链接之一变红
{
// assert (x != null);
// assert isRed(x) && !isRed(x.left) && !isRed(x.left.left);
flipColors(x);
if (isRed(x.right.left))
{
x.right = rotateRight(x.right);
x = rotateLeft(x);
flipColors(x);
}
return x;
} private Node moveRedRight(Node x) // x 红而 x.right 和 x.right.left 都是黑的,调整使得两黑链接之一变红
{
// assert (x != null);
// assert isRed(x) && !isRed(x.right) && !isRed(x.right.left);
flipColors(x);
if (isRed(x.left.left))
{
x = rotateRight(x);
flipColors(x);
}
return x;
} private Node balance(Node x) // 右链接红色、连续两层左链接红色以及左右链接都是红色的状况,分别调整
{
// assert (x != null);
if (isRed(x.right))
x = rotateLeft(x);
if (isRed(x.left) && isRed(x.left.left))
x = rotateRight(x);
if (isRed(x.left) && isRed(x.right))
flipColors(x);
x.size = 1 + size(x.left) + size(x.right);
return x;
} public Key min()
{
if (isEmpty())
throw new NoSuchElementException("\n<delete> empty.\n");
return minKernel(root).key;
} private Node minKernel(Node x)
{
if (x.left == null)
return x;
return minKernel(x.left);
} public Key max()
{
if (isEmpty())
throw new NoSuchElementException("\n<max> empty.\n");
return maxKernel(root).key;
} private Node maxKernel(Node x)
{
if (x.right == null)
return x;
return maxKernel(x.right);
} public Key floor(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<floor> key == null.\n");
if (isEmpty())
throw new NoSuchElementException("\n<floor> empty.\n");
Node x = floorKernel(root, key);
return (x == null) ? null : x.key;
} private Node floorKernel(Node x, Key key)
{
if (x == null)
return null;
int cmp = key.compareTo(x.key);
if (cmp == 0)
return x;
if (cmp < 0)
return floorKernel(x.left, key);
Node t = floorKernel(x.right, key);
return (t == null) ? x : t;
} public Key ceiling(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<ceiling> key == null.\n");
if (isEmpty())
throw new NoSuchElementException("\n<ceiling> empty.\n");
Node x = ceilingKernel(root, key);
return (x == null) ? null : x.key;
} private Node ceilingKernel(Node x, Key key)
{
if (x == null)
return null;
int cmp = key.compareTo(x.key);
if (cmp == 0)
return x;
if (cmp > 0)
return ceilingKernel(x.right, key);
Node t = ceilingKernel(x.left, key);
return (t == null) ? x : t;
} public Key select(int k)
{
if (k < 0 || k >= size())
throw new IllegalArgumentException("\n<select> k < 0 || k >= size().\n");
return selectKernel(root, k).key;
} private Node selectKernel(Node x, int k)
{
if (x == null)
return null;
int t = size(x.left);
if (k <t)
return selectKernel(x.left, k);
if (k > t)
return selectKernel(x.right, k - t - 1);
return x;
} public int rank(Key key)
{
if (key == null)
throw new IllegalArgumentException("\n<rank> key == null.\n");
return rankKernel(key, root);
} private int rankKernel(Key key, Node x)
{
if (x == null)
return 0;
int cmp = key.compareTo(x.key);
if (cmp < 0)
return rankKernel(key, x.left);
if (cmp > 0)
return 1 + size(x.left) + rankKernel(key, x.right);
return size(x.left);
} public Iterable<Key> keys()
{
if (isEmpty())
return new Queue<Key>();
Key lo = min(), hi = max();
if (lo == null)
throw new IllegalArgumentException("\n<iterable> lo == null.\n");
if (hi == null)
throw new IllegalArgumentException("\n<iterable> hi == null.\n");
Queue<Key> queue = new Queue<Key>();
// if (isEmpty() || lo.compareTo(hi) > 0) return queue;
keysKernel(root, queue, lo, hi);
return queue;
} private void keysKernel(Node x, Queue<Key> queue, Key lo, Key hi)
{
if (x == null)
return;
int cmplo = lo.compareTo(x.key), cmphi = hi.compareTo(x.key);
if (cmplo < 0)
keysKernel(x.left, queue, lo, hi);
if (cmplo <= 0 && cmphi >= 0)
queue.enqueue(x.key);
if (cmphi > 0)
keysKernel(x.right, queue, lo, hi);
} public Iterable<Key> levelOrder()
{
Queue<Key> keys = new Queue<Key>();
Queue<Node> queue = new Queue<Node>();
for (queue.enqueue(root); !queue.isEmpty();)
{
Node x = queue.dequeue();
if (x == null)
continue;
keys.enqueue(x.key);
queue.enqueue(x.left);
queue.enqueue(x.right);
}
return keys;
} public int size(Key lo, Key hi)
{
if (lo == null)
throw new IllegalArgumentException("\n<size> lo == null.\n");
if (hi == null)
throw new IllegalArgumentException("\n<size> hi == null.\n");
if (lo.compareTo(hi) > 0)
return 0;
if (contains(hi))
return rank(hi) - rank(lo) + 1;
return rank(hi) - rank(lo);
} public int height()
{
return heightKernel(root);
} private int heightKernel(Node x)
{
if (x == null)
return -1;
return 1 + Math.max(heightKernel(x.left), heightKernel(x.right));
} private boolean check()
{
if (!isBST())
StdOut.println("\n<check> Not in symmetric order.\n");
if (!isSizeConsistent())
StdOut.println("\n<check> Subtree counts not consistent.\n");
if (!isRankConsistent())
StdOut.println("\n<check> Ranks not consistent.\n");
if (!is23())
StdOut.println("\n<check> Not a 2 - 3 tree.\n");
if (!isBalanced())
StdOut.println("\n<check> Not balanced.\n");
return isBST() && isSizeConsistent() && isRankConsistent() && is23() && isBalanced();
} private boolean isBST()
{
return isBSTKernel(root, null, null);
} private boolean isBSTKernel(Node x, Key min, Key max)
{
if (x == null)
return true;
if (min != null && x.key.compareTo(min) <= 0)
return false;
if (max != null && x.key.compareTo(max) >= 0)
return false;
return isBSTKernel(x.left, min, x.key) && isBSTKernel(x.right, x.key, max);
} private boolean isSizeConsistent()
{
return isSizeConsistentKernel(root);
} private boolean isSizeConsistentKernel(Node x)
{
if (x == null)
return true;
if (x.size != 1 + size(x.left) + size(x.right))
return false;
return isSizeConsistentKernel(x.left) && isSizeConsistentKernel(x.right);
} private boolean isRankConsistent()
{
for (int i = 0; i < size(); i++)
{
if (i != rank(select(i)))
return false;
}
for (Key key : keys())
{
if (key.compareTo(select(rank(key))) != 0)
return false;
}
return true;
} private boolean is23()
{
return is23Kernel(root);
} private boolean is23Kernel(Node x)
{
if (x == null)
return true;
if (isRed(x.right))
return false;
if (x != root && isRed(x) && isRed(x.left))
return false;
return is23Kernel(x.left) && is23Kernel(x.right);
} private boolean isBalanced()
{
int black = 0; // 从 root 到 min 节点的路径长
for(Node x = root;x != null; x = x.left)
{
if (!isRed(x))
black++;
}
return isBalancedKernel(root, black);
} private boolean isBalancedKernel(Node x, int black)
{
if (x == null)
return black == 0;
if (!isRed(x))
black--;
return isBalancedKernel(x.left, black) && isBalancedKernel(x.right, black);
} public static void main(String[] args)
{
class01<String, Integer> st = new class01<String, Integer>();
for (int i = 0; !StdIn.isEmpty(); i++)
{
String key = StdIn.readString();
st.put(key, i);
} for (String s : st.levelOrder())
StdOut.println(s + " " + st.get(s)); StdOut.println();
for (String s : st.keys())
StdOut.println(s + " " + st.get(s));
}
}//

《算法》第三章部分程序 part 3的更多相关文章

  1. 《算法》第三章部分程序 part 6

    ▶ 书中第三章部分程序,加上自己补充的代码,包含双向索引表.文建索引.稀疏向量类型 ● 双向索引表 package package01; import edu.princeton.cs.algs4.S ...

  2. 《算法》第三章部分程序 part 5

    ▶ 书中第三章部分程序,加上自己补充的代码,包含公共符号表.集合类型 ● 公共符号表,用于普通查找表的基本类 package package01; import java.util.NoSuchEle ...

  3. 《算法》第三章部分程序 part 4

    ▶ 书中第三章部分程序,加上自己补充的代码,包括散列表.线性探查表 ● 散列表 package package01; import edu.princeton.cs.algs4.Queue; impo ...

  4. 《算法》第三章部分程序 part 2

    ▶ 书中第三章部分程序,加上自己补充的代码,平衡二叉搜索树 ● 平衡二叉搜索树 package package01; import java.util.NoSuchElementException; ...

  5. 《算法》第三章部分程序 part 1

    ▶ 书中第三章部分程序,加上自己补充的代码,包括单词频率统计,(单链表)顺序查找表,二分查找表 ● 单词频率统计 package package01; import edu.princeton.cs. ...

  6. 《算法》第二章部分程序 part 3

    ▶ 书中第二章部分程序,加上自己补充的代码,包括各种优化的快排 package package01; import edu.princeton.cs.algs4.In; import edu.prin ...

  7. 《算法》第一章部分程序 part 1

    ▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...

  8. 《算法》第二章部分程序 part 5

    ▶ 书中第二章部分程序,加上自己补充的代码,包括利用优先队列进行多路归并和堆排序 ● 利用优先队列进行多路归并 package package01; import edu.princeton.cs.a ...

  9. 《算法》第二章部分程序 part 4

    ▶ 书中第二章部分程序,加上自己补充的代码,包括优先队列和索引优先队列 ● 优先队列 package package01; import java.util.Comparator; import ja ...

随机推荐

  1. Delphi:窗体的扩展样式GWL_EXSTYLE用于SetWindowLong

    SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_TRANSPARENT or WS_EX_ ...

  2. sqlserver 全局事务查询

    -- 此语句用于查看最老的活动事务.未完成的分布式事务或复制事务的信息. dbcc opentran -- 通过动态管理视图查看活动事务 select*from sys.dm_tran_active_ ...

  3. html多个水平并列组件自适应等高的做法

    做一个div盒子,设置over-flow:hidden,设置高度为auto.然后再盒子里排列若干inline-block,inline元素. 自适应的话常用做法是用line-height,font-s ...

  4. 黄聪:WordPress 启用HTTPS设置(转)

    HTTPS已经成为网站的一种趋势,得益于数以万计的开发者和百万计的玩家,Wordpress启用HTTPS过程相当简单.下面就把Wordpress启用HTTPS访问的过程记录一下,以供参考. 一. 修改 ...

  5. [蓝桥杯]ALGO-16.算法训练_进制转换

    问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...

  6. 力奋github:https://github.com/birdstudiocn

    我的github地址https://github.com/birdstudiocn

  7. 杂项:TMT(数字媒体产业)

    ylbtech-杂项:TMT(数字媒体产业) TMT(Technology,Media,Telecom),是科技.媒体和通信三个英文单词的缩写的第一个字头,整合在一起.含义实际是未来(互联网)科技.媒 ...

  8. 学习笔记之Everything

    Everything (software) - Wikipedia https://en.wikipedia.org/wiki/Everything_(software) Everything is ...

  9. JAVA虚拟机关闭钩子(Shutdown Hook)

    程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.JAVA中的ShutdownHook提供了比较好的方案. JDK提供了Java.Run ...

  10. 标准C库函数

    标准库函数由15个头文件组成 1.math.h 1.1 绝对值函数 1.2 幂函数.开平方函数 1.3 指数函数.对数函数 1.5 三角函数 注意参数范围: 1.6 取整函数.取余函数 2.字符串处理 ...